Cách đặt giá trị mặc định trong cấu trúc Go


143

Có nhiều câu trả lời / kỹ thuật cho câu hỏi dưới đây:

  1. Làm cách nào để đặt giá trị mặc định cho cấu trúc golang?
  2. Làm thế nào để khởi tạo cấu trúc trong golang

Tôi có một vài câu trả lời nhưng cần thảo luận thêm.



@icza Bạn trả lời sẽ cung cấp một cách để làm điều đó nhưng đi theo Tiêu đề Câu hỏi, nó không có cách nào tương tự hoặc có thể tìm kiếm được vì đây là một câu hỏi rất cụ thể. Tôi sẽ thêm các liên kết trong câu trả lời của tôi mặc dù.
Prateek

Có hai câu hỏi ở đây, chọn một. Giả sử bạn chọn cho câu hỏi đầu tiên (theo tiêu đề câu hỏi), vui lòng cụ thể hơn về nghiên cứu trước đây của bạn và nơi các câu trả lời khác của bạn yêu cầu thảo luận nhiều hơn ,.
Duncan Jones

Câu trả lời:


96

Một ý tưởng có thể là viết hàm xây dựng riêng

//Something is the structure we work with
type Something struct {
     Text string 
     DefaultText string 
} 
// NewSomething create new instance of Something
func NewSomething(text string) Something {
   something := Something{}
   something.Text = text
   something.DefaultText = "default text"
   return something
}

6
Vâng, đây là một trong những cách mà tôi cũng đã đề cập trong câu trả lời của mình nhưng không có cách nào chúng tôi có thể buộc bất cứ ai chỉ sử dụng chức năng này.
Prateek

@Prateek đó là cái này hoặc sử dụng một giao diện, nó sẽ xấu và quá phức tạp.
OneOfOne

31
@Prateek có, bạn có thể buộc mọi người sử dụng hàm tạo này nếu bạn chỉ đơn giản làm cho kiểu đó không được thể hiện. Bạn có thể xuất hàm NewSomethingvà thậm chí các trường TextDefaultText, nhưng không xuất kiểu cấu trúc something.
Amit Kumar Gupta

1
Vấn đề tồi tệ hơn ... nếu một bên thứ ba (ví dụ thư viện) được sử dụng để khởi tạo cấu trúc của bạn ( reflect.New()chẳng hạn như thông qua ), bạn không thể biết về chức năng xuất xưởng được đặt tên đặc biệt của mình. Trong trường hợp đó, và thiếu ngôn ngữ bị thay đổi, chỉ có một giao diện (mà thư viện có thể kiểm tra) sẽ làm, tôi nghĩ vậy.
edam

1
Thật tốt khi đặt mặc định, nhưng đôi khi, tôi có thể muốn ghi đè mặc định. Trong trường hợp này, tôi sẽ không thể khởi tạo cấu trúc với giá trị không phải là mặc định. một chút khó chịu đối với tôi
Juliatzin

68
  1. Buộc một phương thức để có được cấu trúc (cách xây dựng).

    Một thiết kế tốt là làm cho kiểu của bạn không được báo cáo, nhưng cung cấp hàm xây dựng được xuất như NewMyType () trong đó bạn có thể khởi tạo chính xác cấu trúc / kiểu của mình. Đồng thời trả về một loại giao diện chứ không phải loại cụ thể và giao diện sẽ chứa mọi thứ người khác muốn làm với giá trị của bạn. Và loại bê tông của bạn phải thực hiện giao diện đó tất nhiên.

    Điều này có thể được thực hiện bằng cách đơn giản làm cho loại chính nó không được quan tâm. Bạn có thể xuất hàm NewS Something và thậm chí các trường Text và DefaultText, nhưng chỉ không xuất kiểu cấu trúc gì đó

  2. Một cách khác để tùy chỉnh mô-đun cho mô-đun của riêng bạn là sử dụng Cấu trúc cấu hình để đặt giá trị mặc định (Tùy chọn 5 trong liên kết) Mặc dù không phải là một cách hay.


7
Đây hiện là một liên kết bị hỏng (404): joneisen.tumblr.com/post/53695478114/golang-and-default-values
Victor Zamanian

3
Nó có sẵn trong máy wayback .
n8henrie

FWIW, tôi nghĩ đó là 'Tùy chọn 3' - ít nhất là trong liên kết máy quay ngược. (Không có 'Tùy chọn 5', ở đó).
decimus phostle

@ m90 để im lặng golint, bạn có thể khai báo chức năng của mình khi trả về loại giao diện công cộng
Thomas Grainger

@ThomasGrainger Nhận xét của tôi dường như đề cập đến một phiên bản trước của câu trả lời này, nó không thực sự có ý nghĩa như thế này nữa :) Tôi sẽ chỉ xóa nó.
m90

32

Một vấn đề với tùy chọn 1 trong câu trả lời của Victor Zamanian là nếu loại không được xuất thì người dùng gói của bạn không thể khai báo đó là loại cho các tham số chức năng, v.v. Một cách khác là sẽ xuất giao diện thay vì cấu trúc ví dụ

package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
    Name string
    Votes uint32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
    return candidate{name, 0}  // enforce the default value here
}

Cho phép chúng tôi khai báo các loại tham số chức năng bằng giao diện Ứng viên đã xuất. Nhược điểm duy nhất tôi có thể thấy từ giải pháp này là tất cả các phương thức của chúng tôi cần được khai báo trong định nghĩa giao diện, nhưng bạn có thể lập luận rằng đó là cách thực hành tốt.


có sẵn để thay đổi biến Tên và Phiếu bầu sau khi gọi Hàm mới?
morteza khadem

Đẹp ví dụ đơn giản.

Votes unit32Votes uint32
Lỗi

@PartyLich cũng phát hiện ra. Nên sửa.
wolfson109

13

Có một cách để làm điều này với các thẻ, cho phép nhiều mặc định.

Giả sử bạn có cấu trúc sau, với 2 thẻ mặc định default0default1 .

type A struct {
   I int    `default0:"3" default1:"42"`
   S string `default0:"Some String..." default1:"Some Other String..."`
}

Bây giờ có thể Đặt mặc định.

func main() {

ptr := &A{}

Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...

Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}

Đây là chương trình hoàn chỉnh trong một sân chơi .

Nếu bạn quan tâm đến một ví dụ phức tạp hơn, hãy nói với các lát và bản đồ, sau đó, hãy xem cTHERy / defaultse


Cảm ơn rất nhiều! Tôi bắt đầu viết mã giống như thư viện đề xuất và tình cờ thấy bài đăng này. Nó thực hiện chính xác những gì bạn mong đợi ( github.com/cTHERy/defaults ). Nếu bạn không có giá trị, nó sẽ đặt mặc định, nhưng nếu bạn đã gán một giá trị cho biến của mình, thì nó sẽ không gán mặc định. Nó hoạt động khá tốt với thư viện yaml.v2.
Nordes


-3
type Config struct {
    AWSRegion                               string `default:"us-west-2"`
}

1
Điều này là không đúng. Tốt nhất, bạn có thể đặt giá trị thẻ trên trường đó và sau đó lấy giá trị của nó bằng phản xạ nhưng ngay cả với cú pháp này là không chính xác (thiếu dấu tích ngược) và bạn chỉ có thể đặt giá trị mặc định cho loại chuỗi. Nếu bạn có cái nhìn sâu sắc về những gì ví dụ này đề cập cụ thể, vui lòng thêm một liên kết để tham khảo.
markeissler
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.