2016-06-22 16 views
6

Tôi đã bắt đầu học Go vài ngày trước và đến bởi điều CGO của nó và trình biên dịch gccgo. Từ sự hiểu biết của tôi điều này cho phép một chương trình Go để biên dịch bằng cách sử dụng trình biên dịch Go và biên dịch các thư viện C bằng cách sử dụng một trình biên dịch C và tham chiếu các thư viện đó từ bên trong một chương trình Go. Điều này thực sự thú vị với tôi bởi vì điều này cho phép chúng tôi tận dụng hiệu suất của C (nếu cần) từ chương trình chính của chúng tôi với chi phí thấp.Sử dụng C (++) trong ứng dụng GoLang để thực hiện

Tuy nhiên tôi không chắc chắn như thế nào ít có nghĩa là, vì vậy tôi hỏi ở đây:

Có trường hợp bạn sẽ tạo ra một thư viện C chỉ để sử dụng nó từ bên trong ứng dụng Go của bạn? Hoặc là tính năng này chỉ để tạo điều kiện sử dụng lại mã C hiện có?

P.S: Tôi nghĩ lúc này CGO không hỗ trợ C++ nhưng có một bài đăng ở đây của ai đó có thể bọc mã C++ bằng cách sử dụng hàm C và gọi chúng thành công.

+1

Rất có thể chỉ để sử dụng lại được. Hầu hết các thư viện lớn (chưa kể OS) có một ràng buộc C, do đó, có khả năng gọi C từ ngôn ngữ của bạn là một chiến thắng lớn cho việc áp dụng ngôn ngữ. – Dan

Trả lời

7

Cgo khá chậm, bởi vì Go phải mess with its runtime and calling conventions theo những cách nhất định để gọi hàm C. Nơi duy nhất nó thực sự có giá trị nó là trường hợp thời gian tính toán đáng kể lùn this cost. Nó tương tự như song song, phân phối, GPU và như vậy lập trình, mặc dù với chi phí khởi động thấp hơn một chút.

Lắp ráp tốt hơn nhiều, vì bạn có thể viết lắp ráp sử dụng quy ước gọi của Go và được xử lý như mã Go gốc, nhưng lắp ráp ít di động hơn, khó đọc hơn và bảo trì nhiều hơn. Trong thực tế, thư viện chuẩn Go viết một số gói mathbig trong gói 9 kiểu.

Gonum là ví dụ về cả hai loại này. Nó sử dụng lắp ráp chung cho một số chức năng có thể được thực hiện nhanh hơn theo cách đó, nhưng nó cũng thúc đẩy blas và động cơ lapack. Nó cung cấp một triển khai thực hiện Go-blas, nhưng C-blas (thường là cuối cùng là Fortran-blas) là nhanh hơn, và đối với các phép tính ma trận lớn hầu như luôn luôn làm giảm chi phí rời khỏi Go.

Nói chung, bạn muốn tránh cgo khi có thể. Chỉ sử dụng nó khi cần thời gian tính toán quan trọng, hoặc bạn cần tương tác với những thứ không tầm thường để tương tác với Go thuần túy, chẳng hạn như đồ họa hoặc trình điều khiển âm thanh hoặc truy cập các thư viện phổ biến như OpenCV. Thậm chí sau đó, nếu bạn thực sự quan tâm đến hiệu suất, nếu có thể nó sẽ đáng để thực hiện một số loại "gọi tổng hợp", nơi bạn có thể lên lịch nhiều cuộc gọi từ phía Bên và thực hiện tất cả cùng một lúc bằng một chuyển ngữ cảnh sang C.

Chỉnh sửa: Đối với C++, có một số vấn đề quan trọng. Nó có thể khó khăn để bọc một số thư viện mà không có một số lớp trừu tượng (vì cgo không thể xử lý bao gồm các tiêu đề C++ đúng cách). Ngoài ra, các lớp C++ với destructors không thực sự được trả về bởi giá trị và phải được cấp phát trên heap. Vì Go không cho phép xác định tài nguyên xác định, bạn phải cung cấp chức năng để giải phóng bộ nhớ một cách rõ ràng và người dùng Go phải nhớ giải phóng tài nguyên.(Có một chức năng mà bạn có thể đọc trong tài liệu gọi là runtime.SetFinalizer nhưng tôi không thể nói rằng tôi từng thấy bất kỳ ai sử dụng nó, và tài liệu tự nó đi kèm với một loạt các cảnh báo)

Chức năng như defer làm điều này dễ quản lý hơn, nhưng nó làm hỏng rất nhiều thứ như RAII làm cho các thực hành C++ hiện đại an toàn hơn.

+0

"Đi phải đình chỉ thời gian chạy của nó theo những cách nhất định để gọi các hàm C" - liệu nó có được ghi chép/thảo luận ở đâu đó không? Xem thêm [câu trả lời của tôi] (http://stackoverflow.com/a/37962500/3169754) và [chủ đề này] (https://groups.google.com/forum/#!topic/golang-nuts/RTtMsgZi88Q). – gavv

+0

Tôi không thể tìm thấy bất kỳ bằng chứng nào cho thấy thời gian chạy bị tạm ngưng. Tôi có thể thiếu một cái gì đó. – gavv

+1

@ g-v Đó là một trong những thứ liên tục trong thông lượng với các phiên bản Go mới. Tôi nghĩ rằng Go đã từng phải dừng hẳn bộ thu gom rác và những thứ khác. Có vẻ như ngày nay, phần lớn nó phải ghi lại một tấn siêu dữ liệu để đáp ứng các quy ước gọi khác nhau: http://dave.cheney.net/2016/01/18/cgo-is-not-go Ngoài ra, nó không thể làm gián đoạn và lên lịch lại goroutine trên một luồng khác trong khi nó nằm trong mã C, điều này là tuyệt đối có thể và không thực hiện, thường là vì lý do hiệu năng, trong mã GO. – LinearZoetrope

1

Trừ khi thư viện C thực hiện nhiều công việc trong một cuộc gọi, tôi sẽ không viết mã C chỉ để thực hiện. Tôi coi cgo chỉ để giao tiếp với mã cũ.

Lý do là chi phí cho bản ngã. Hiện tại các cuộc gọi hàm thành hàm cgo là between 50 and 100 times slower than function calls to Go code. Chi phí của các cuộc gọi hàm cgo là gây sốc.

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