Chúng ta hãy nói rằng chúng ta muốn thực hiện sau tính toán:chức năng lồng nhau gọi trong GO
outval/err = f3(f3(f1(inval))
nơi mỗi f1
, f2
, f3
có thể thất bại với một lỗi tại thời điểm đó chúng tôi dừng việc tính toán và thiết lập err
lỗi được trả về bởi hàm lỗi. (Tất nhiên, làm tổ có thể tùy tiện lâu)
Trong các ngôn ngữ như C++/Java/C# nó có thể dễ dàng thực hiện bằng cách f1
, f2
và f3
ném một ngoại lệ và kèm theo các tính toán trong một khối try-catch, trong khi ở các ngôn ngữ như Haskell chúng ta có thể sử dụng monads để thay thế.
Bây giờ tôi đang cố gắng để thực hiện nó trong GO và cách tiếp cận duy nhất tôi có thể nghĩ đến là rõ ràng nếu-khác thang đó là khá tiết. Tôi không có vấn đề nếu chúng ta không thể tổ chức các cuộc gọi, nhưng theo ý kiến của tôi thêm kiểm tra lỗi sau mỗi dòng trong mã trông xấu xí và nó phá vỡ dòng chảy. Tôi muốn biết nếu có cách nào tốt hơn để làm điều đó.
Edit: Chỉnh sửa theo nhận xét của peterSO
Dưới đây là ví dụ cụ thể và thực hiện đơn giản
package main
import "fmt"
func f1(in int) (out int, err error) {
return in + 1, err
}
func f2(in int) (out int, err error) {
return in + 2, err
}
func f3(in int) (out int, err error) {
return in + 3, err
}
func calc(in int) (out int, err error) {
var temp1, temp2 int
temp1, err = f1(in)
if err != nil {
return temp1, err
}
temp2, err = f2(temp1)
if err != nil {
return temp2, err
}
return f3(temp2)
}
func main() {
inval := 0
outval, err := calc3(inval)
fmt.Println(inval, outval, err)
}
Những gì tôi đang cố gắng để minh họa là, chức năng calc hiện một số tính toán có thể với sự giúp đỡ của các chức năng thư viện mà có thể thất bại và ngữ nghĩa là nếu bất kỳ cuộc gọi không thành công calc tuyên truyền lỗi cho người gọi (tương tự như không xử lý ngoại lệ). Theo tôi, mã cho calc là xấu xí.
giữa cho trường hợp cụ thể này, nơi tất cả các chức năng thư viện có chính xác cùng một chữ ký, chúng ta có thể làm cho đoạn code tốt hơn (Tôi đang sử dụng ý tưởng từ http://golang.org/doc/articles/wiki/#tmp_269)
func saferun(f func (int) (int, error)) func (int, error) (int, error) {
return func (in int, err error) (int, error) {
if err != nil {
return in, err
}
return f(in)
}
}
Sau đó, chúng ta có thể xác định lại calc như
func calc(in int) (out int, err error) {
return saferun(f3)(saferun(f2)(f1(in)))
}
hoặc dưới dạng
func calc(in int) (out int, err error) {
sf2 := saferun(f2)
sf3 := saferun(f3)
return sf3(sf2(f1(in)))
}
Nhưng không có generics s upport, tôi không chắc chắn làm thế nào tôi có thể sử dụng phương pháp này cho bất kỳ tập hợp các chức năng thư viện.
Cảm ơn bạn đã trả lời nhưng tôi không chắc rằng tôi hiểu cách tiếp cận của bạn. Điều gì xảy ra nếu tôi không kiểm soát chữ ký của f1, f2, f3, v.v. vì chúng là các hàm thư viện.Trong quan điểm khiêm tốn của tôi xử lý cơ sở hạ tầng trong các ngôn ngữ khác không yêu cầu bạn phải có một kiểm soát – Suyog
Suyog, trích dẫn từ câu hỏi ban đầu của bạn, "... thực hiện bằng cách có f1, f2 và f3 ném một ngoại lệ ...." có vẻ như bạn cho phép thay đổi f1, f2 và f3 để ném ngoại lệ. Làm họ hoảng loạn không khác gì. Panic là cơ chế có sẵn trong Go để thư giãn stack từ độ sâu tùy ý, trả về một giá trị trong tiến trình. Nó không phải là cách thành ngữ và ưu tiên để xử lý lỗi trong Go, nhưng nó là cơ chế sẽ làm những gì bạn yêu cầu. – Sonia
Tôi có nghĩa là f1, f2, f3 đã được xác định để ném một ngoại lệ. Xin lỗi vì từ ngữ xấu. Trong ngôn ngữ như JAVA, nhiều chức năng thư viện được định nghĩa để ném một ngoại lệ, trong khi trong GO có vẻ như mẫu là có chức năng thư viện trả về lỗi. Vì vậy, vấn đề tôi đang phải đối mặt là tôi phải kiểm tra lỗi ngay lập tức đó là kết quả bằng văn bản lặp đi lặp lại mã. – Suyog