Tại sao không có tướng trong Go?


126

Tuyên bố miễn trừ trách nhiệm: Tôi mới chỉ chơi với Go được một ngày, vì vậy rất có thể tôi đã bỏ lỡ rất nhiều.

Có ai biết tại sao không có hỗ trợ thực sự cho thuốc generic / mẫu / whatsInAName trong Go không? Vì vậy, có một cái chung map, nhưng được cung cấp bởi trình biên dịch, trong khi một lập trình viên Go không thể viết bản thực hiện của riêng mình. Với tất cả các cuộc nói chuyện về việc biến Go thành trực giao nhất có thể, tại sao tôi có thể SỬ DỤNG một loại chung chung nhưng không TẠO một loại mới?

Đặc biệt là khi nói đến lập trình chức năng, có lambdas, thậm chí đóng, nhưng với một hệ thống kiểu tĩnh thiếu khái quát, làm thế nào để tôi viết, tốt, các hàm bậc cao hơn như thế filter(predicate, list)nào? OK, danh sách được liên kết và tương tự có thể được thực hiện với interface{}hy sinh loại an toàn.

Vì một tìm kiếm nhanh trên SO / Google không tiết lộ bất kỳ thông tin chi tiết nào, có vẻ như thuốc generic, nếu có, sẽ được thêm vào Go như một suy nghĩ sau. Tôi tin tưởng rằng Thompson sẽ làm tốt hơn những người Java, nhưng tại sao lại bỏ qua những điều chung chung? Hay họ đã lên kế hoạch và chỉ chưa thực hiện?


Tôi nghĩ rằng nó đáng để chỉ ra: sử dụng giao diện {} không hy sinh loại an toàn. Đây là một loại và có thể được xác nhận (không truyền) cho các loại khác, nhưng các xác nhận này vẫn gọi kiểm tra thời gian chạy để duy trì an toàn loại.
cthom06

12
interface{}hy sinh loại tĩnh an toàn. Tuy nhiên, đây là một khiếu nại hơi lạ khi đề cập đến Đề án là đoạn tiếp theo, vì Đề án thường không có kiểm tra kiểu tĩnh.
poolie

@poolie: Điều tôi quan tâm là gắn bó với MỘT mô hình trong một ngôn ngữ. Hoặc tôi đang sử dụng XOR loại an toàn tĩnh.

2
btw nó đánh vần là 'Đi', không phải 'GO', như bạn có thể thấy trên golang.org. Và nó phân biệt chữ hoa chữ thường. :-)
poolie

1
Làm thế nào về github.com/facebookgo/generics ?
Thellimist

Câu trả lời:


78

câu trả lời này bạn sẽ tìm thấy ở đây: http://golang.org/doc/faq#generics

Tại sao Go không có loại chung chung?

Generics cũng có thể được thêm vào một số điểm. Chúng tôi không cảm thấy khẩn cấp cho họ, mặc dù chúng tôi hiểu một số lập trình viên làm.

Generics là thuận tiện nhưng chúng có chi phí phức tạp trong hệ thống loại và thời gian chạy. Chúng tôi chưa tìm thấy một thiết kế mang lại giá trị tương xứng với sự phức tạp, mặc dù chúng tôi vẫn tiếp tục nghĩ về nó. Trong khi đó, các bản đồ và lát cắt tích hợp của Go, cộng với khả năng sử dụng giao diện trống để xây dựng các thùng chứa (với hộp thư rõ ràng) có nghĩa là trong nhiều trường hợp có thể viết mã mà tính tổng quát sẽ kích hoạt, nếu kém trơn tru hơn.

Đây vẫn là một vấn đề mở.


14
@amoebe, "giao diện trống", đánh vần interface{}, là loại giao diện cơ bản nhất và mọi đối tượng đều cung cấp nó. Nếu bạn tạo một thùng chứa chúng, nó có thể chấp nhận bất kỳ đối tượng (không nguyên thủy) nào. Vì vậy, nó rất giống với một container chứa Objectstrong Java.
poolie

4
@YinWang Generics không đơn giản trong môi trường suy luận kiểu. Quan trọng hơn; giao diện {} không tương đương với các con trỏ void * trong C. Tương tự tốt hơn sẽ là các loại id System.Object hoặc Objective-C của C #. Thông tin loại được bảo tồn và có thể được "đúc" (thực sự khẳng định) trở lại loại bê tông của nó. Nhận thông tin chi tiết tại đây: golang.org/ref/spec#Type_assertions
xương sống

2
System.Object (hoặc Object's Java per se) của @tbone về cơ bản là những gì tôi muốn nói là "Con trỏ void của C" (bỏ qua phần mà bạn không thể thực hiện số học con trỏ trong các ngôn ngữ đó). Đó là nơi thông tin loại tĩnh bị mất. Một diễn viên sẽ không giúp được gì nhiều vì bạn sẽ gặp lỗi thời gian chạy.
Ian

1
Các mẫu của @ChristopherPfohl D dường như có ít thời gian biên dịch hơn một chút và thông thường bạn không tạo nhiều mã với các mẫu hơn bình thường (trên thực tế, bạn có thể kết thúc với íthơn tùy theo hoàn cảnh).
Khối

3
@ChristopherPfohl Tôi nghĩ chỉ có các thế hệ Java mới có vấn đề về quyền anh / unboxing cho các kiểu nguyên thủy? Chung chung thống nhất của C # không có vấn đề.
ca9163d9

32

Đi 2

Có một bản thiết kế phác thảo cho thuốc generic tại https://blog.golang.org/go2draft .

Đi 1

Russ Cox, một trong những cựu chiến binh Go đã viết một bài đăng trên blog có tựa đề The Dilemma chung , trong đó anh ta hỏi

Bạn có muốn lập trình viên chậm, trình biên dịch chậm và nhị phân cồng kềnh, hoặc thời gian thực hiện chậm?

Các lập trình viên chậm là kết quả của việc không có tướng, trình biên dịch chậm được gây ra bởi C ++ giống như tướng và thời gian thực hiện chậm xuất phát từ cách tiếp cận không đóng hộp mà Java sử dụng.

Khả năng thứ tư không được đề cập trong blog là đi theo lộ trình C #. Tạo mã chuyên dụng như trong C ++, nhưng trong thời gian chạy khi cần thiết. Tôi thực sự thích nó, nhưng Go rất không giống C # nên có lẽ điều này không thể áp dụng được

Tôi nên đề cập đến rằng việc sử dụng phổ biến Java 1.4 như kỹ thuật lập trình chung trong đi rằng phôi để interface{}bị chính xác những vấn đề tương tự như đấm bốc-unboxing (vì đó là những gì chúng tôi đang làm), bên cạnh việc mất an toàn kiểu thời gian biên dịch. Đối với các loại nhỏ (như ints) Go tối ưu hóa interface{}loại sao cho danh sách các int được truyền tới giao diện {} chiếm một vùng bộ nhớ liền kề và chỉ chiếm không gian gấp đôi so với int thông thường. interface{}Mặc dù vậy, vẫn còn chi phí kiểm tra thời gian chạy trong khi truyền từ . Tham khảo .

Tất cả các dự án có thêm hỗ trợ chung để đi (có một vài trong số chúng và tất cả đều thú vị) thống nhất đi theo lộ trình C ++ của việc tạo mã thời gian biên dịch.


Giải pháp cho vấn đề nan giải này của tôi sẽ là Đi đến mặc định là "thời gian thực hiện chậm" với tùy chọn cấu hình chương trình và biên dịch lại các phần nhạy cảm hiệu suất nhất trong chế độ "trình biên dịch chậm và nhị phân cồng kềnh". Thật tệ khi mọi người thực sự thực hiện những thứ như vậy có xu hướng đi theo con đường C ++.
user7610

1
Nó đã được đề cập rằng các loại nhỏ (tức là int) được lưu trữ []interface{}sử dụng gấp đôi RAM như []int. Mặc dù đúng, các loại nhỏ hơn (ví dụ byte) sử dụng tới 16 lần RAM như []byte.
BMiner

Thực sự không có vấn đề nan giải với phương pháp C ++. Nếu một lập trình viên chọn viết mã mẫu, lợi ích của việc đó phải vượt qua chi phí biên dịch chậm. Nếu không, anh chỉ có thể làm theo cách cũ.
John Z. Li

Vấn đề nan giải là về cách tiếp cận để lựa chọn. Nếu bạn giải quyết tình trạng khó xử bằng cách tiếp cận C ++, tình huống khó xử sẽ được giải quyết.
dùng7610

9

Mặc dù hiện tại tướng không được tích hợp sẵn, nhưng có một số triển khai bên ngoài của thuốc generic, sử dụng nhận xét trong các kết hợp với các tiện ích nhỏ tạo mã.

Đây là một cách thực hiện như vậy: http://clipperhouse.github.io/gen/


1

Trên thực tế, theo bài đăng này :

Nhiều người đã kết luận (không chính xác) rằng vị trí của đội Go là đội Go sẽ không bao giờ có tướng. Trái lại, chúng tôi hiểu rằng các thế hệ tiềm năng có, cả hai để làm cho Go trở nên linh hoạt và mạnh mẽ hơn và làm cho Go trở nên phức tạp hơn nhiều. Nếu chúng ta muốn thêm thuốc generic, chúng tôi muốn thực hiện nó theo cách có được sự linh hoạt và sức mạnh càng nhiều với độ phức tạp càng ít càng tốt.


-1

Đa hình tham số (genericics) đang được xem xét cho Go 2 .

Cách tiếp cận này sẽ giới thiệu khái niệm hợp đồng , có thể được sử dụng để thể hiện các ràng buộc đối với các tham số loại:

contract Addable(a T) {
  a + a // Could be += also
}

Hợp đồng như vậy sau đó có thể được sử dụng:

func Sum(type T Addable)(l []T) (total T) {
  for _, e := range l {
    total += e
  }
  return total
}

Đây là một đề xuất ở giai đoạn này.


filter(predicate, list)Chức năng của bạn có thể được thực hiện với một tham số loại như thế này:

func Filter(type T)(f func(T) bool, l []T) (result []T) {
  for _, e := range l {
    if f(e) {
      result = append(result, e)
    }
  }
  return result
}

Trong trường hợp này, không cần phải hạn chế T.


1
Nếu bạn đang đọc câu trả lời này ngày hôm nay, hãy lưu ý rằng các hợp đồng đã bị loại bỏ khỏi đề xuất dự thảo: go.googlesource.com/proposed/+/refs/heads/master/design/iêu
jub0bs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.