2014-07-07 21 views
8

Tôi là người mới tham gia Go và tôi đã chiến đấu với vấn đề này hầu như cả ngày hôm nay.giao diện {} để chuyển đổi loại chức năng

Xét Tôi có những:

type HandlerType func() 
var object interface{} 
var typedObject HandlerType 

tôi thể gán một chức năng để biến typedObject như thế này:

typedHandler = func() { 
    fmt.Println("in a handler!\n") 
} 

Nhưng những gì tôi cần làm là để vượt qua mà chức năng xử lý như một biến giao diện {} và sau đó chuyển đổi nó thành HandlerType mà tôi có thể gọi sau

Tôi đã thử điều này nhưng nó ném một lỗi:

typedHandler = object.(HandlerType) 

kết quả trong:

interface conversion: interface is func(), not main.HandlerType

Về cơ bản tôi cần phải đăng ký chức năng có ký hiệu khác mà không cần chuyển đổi loại bổ sung trước khi đăng ký. Vì vậy, thay vì làm điều này:

registerHandler(HandlerTypeString(func() string { ... })) 
registerHandler(HandlerTypeVoid(func() { ... })) 

Tôi muốn đăng ký xử lý như sau:

registerHandler(func() string { ... }) 
registerHandler(func() { ... }) 

.. và tôi không muốn liên quan đến phản ánh tại thời điểm một cuộc gọi handler sau

Có thể không?

Sửa: Tôi đã tạo một sân chơi: http://play.golang.org/p/UlwqkHjt_P

Vì vậy, như tôi hiểu không có cách nào để vượt qua một số chức năng tùy ý như giao diện {} và sau đó bằng cách nào đó chuyển nó sang HandlerType hoặc một số được xác định trước khác chức năng loại vì vậy tôi sẽ có thể gọi nó mà không cần sử dụng sự phản ánh?

Edit2: Tôi đã đưa ra giải pháp này: http://play.golang.org/p/4gUxsgmiPf

Không nên có bất kỳ hình phạt hiệu suất trong thời gian chạy với mã này. Nhưng ai đó có thể nghĩ ra cách khác để triển khai chức năng này mà không cần giao diện {}?

+1

Hiển thị mã đầy đủ. 'typedHandler = object. (HandlerType)' ** sẽ ** làm việc nếu đối tượng (thuộc kiểu 'interface {}') thực sự chứa một đối tượng 'HandlerType'. Hiển thị mã có thể phát trên sân chơi. – Volker

+1

Một điều nữa: Nếu bạn là người mới, bạn nên tránh 'giao diện {}'. Finde một số cách khác, nhà văn thích hợp Go mã. Một người mới cho 'giao diện {} 'ma thuật có mùi giống như chuyển ngữ mã từ một số ngôn ngữ khác. – Volker

+0

Tôi đã thêm một sân chơi nơi tôi nghĩ rằng tôi đã thực hiện rõ ràng về những gì tôi muốn hoàn thành :) – user3668351

Trả lời

4

Bạn có thể không, đó là một loại khác nhau, bạn có thể chỉ cần sử dụng object.(func()), object.(func() string) vv

func main() { 
    type HandlerType func() 
    var object interface{} = func() { 
     fmt.Println("eureka!") 
    } 
    if f, ok := object.(func()); ok { 
     HandlerType(f)() 
    } 
} 
+0

Cảm ơn bạn! Bây giờ tôi đã có cách để thực hiện những gì tôi muốn. http://play.golang.org/p/4gUxsgmiPf – user3668351

+0

Thực tế đối với mẫu cụ thể đó, bạn có thể nên sử dụng giao diện như @Elwinar được đề xuất. – OneOfOne

6

Có một số quan niệm sai lầm nhỏ trong câu hỏi của bạn:

  1. Loại xác nhận không được sử dụng để truyền các loại. Tất cả những gì nó làm là kiểm tra xem một biến có thuộc kiểu đã cho hay không và trả về biến này dưới dạng kiểu cơ bản này. Thao tác này trả lại lỗi trong trường hợp của bạn, điều này là bình thường do func() không phải là loại HandlerFunc.

  2. Bạn không cần phải làm bất cứ điều gì để chuyển một biến làm thông số trong hàm chấp nhận interface{}. Mỗi loại ngầm thực hiện giao diện trống.

  3. A func() không phải là HandlerType, ngay cả khi HandlerType được xác định bởi type HandlerType func(). Định nghĩa không liên quan gì đến điều đó.

Điều bạn muốn làm là không thể. Tôi không phải là một chuyên gia với sự phản ánh, nhưng tôi không nghĩ rằng sự phản chiếu cũng có thể giải quyết vấn đề của bạn.

Điều đó nói rằng, phương pháp đăng ký của bạn nên xác định giao diện mà tất cả các đối tượng đã đăng ký phải triển khai và sử dụng giao diện này làm loại thông số. Hãy xem ví dụ database/sql gói Register.

0

Bạn có thể thực hiện việc này ngay bây giờ với reflect.MakeFunc Có một ví dụ về cách thực hiện:

Các vấn đề liên quan