Tin tức chung·Hacker News·0 lượt xem

Quy ước đặt tên Convention: Hướng dẫn thực hành

Go Naming Conventions: A Practical Guide

AI Summary

Bài viết này đi sâu vào các quy ước đặt tên trong Go, một yếu tố cực kỳ quan trọng để viết code rõ ràng và dễ bảo trì. Nó phác thảo các quy tắc nghiêm ngặt cho định danh (identifier), bao gồm các ký tự cho phép (chữ cái, chữ số, dấu gạch dưới), không được bắt đầu bằng chữ số và không được trùng với từ khóa (keyword) của ngôn ngữ. Về các hướng dẫn thực tế, các lập trình viên nên áp dụng `camelCase` cho các định danh không xuất khẩu (unexported) và `PascalCase` cho các định danh xuất khẩu (exported). Việc xử lý các từ viết tắt (acronym) cần nhất quán, tránh sử dụng ký tự không phải ASCII, và đặc biệt là không được trùng lặp với các kiểu dữ liệu (built-in types), hàm (functions) hay tên gói (imported package names) có sẵn trong Go. Nói tóm lại, việc hiểu và áp dụng đúng các quy ước đặt tên này sẽ giúp code trở nên dễ đọc hơn rất nhiều, đồng thời giảm thiểu các lỗi tiềm ẩn.

Chọn đúng tên trong cơ sở mã của bạn là một phần quan trọng (và đôi khi khó khăn!) Trong quá trình lập trình trong Go. Đó là một điều nhỏ nhưng tạo nên sự khác biệt lớn — những cái tên hay làm cho mã của bạn rõ ràng hơn, hơn nữa...

Chọn đúng tên trong cơ sở mã của bạn là một phần quan trọng (và đôi khi khó khăn!) của việc lập trình trong Go. Đó là một điều nhỏ tạo nên sự khác biệt lớn — những cái tên hay làm cho mã của bạn rõ ràng hơn, dễ dự đoán hơn và dễ điều hướng hơn; những cái tên xấu làm điều ngược lại.

Go có những quy ước khá mạnh mẽ — và một vài quy tắc cứng nhắc — để đặt tên cho mọi thứ. Trong bài đăng này, chúng tôi sẽ giải thích các quy tắc và quy ước này, cung cấp một số mẹo thiết thực và trình bày một số ví dụ về tên tốt và tên xấu trong Go. Nếu bạn chưa quen với ngôn ngữ, tất cả thông tin này có thể cảm thấy như rất nhiều để tiếp nhận, nhưng nó sẽ nhanh chóng trở thành bản chất thứ hai với một chút thực hành 😊

Mã định danh

Hãy bắt đầu với các quy tắc cứng cho mã định danh. Theo định danh, ý tôi là các tên mà bạn sử dụng cho các biến, hằng số, loại, hàm, tham số, trường cấu trúc, phương thức và trình nhận trong mã của bạn.

  • Mã định danh chỉ có thể chứa các chữ cái unicode, chữ số và dấu gạch dưới.
  • Mã định danh không thể bắt đầu bằng một chữ số.
  • Bạn không thể sử dụng bất kỳ từ khóa Go nào sau đây làm định danh:
 break        default      func         interface    select
case         defer        go           map          struct
chan         else         goto         package      switch
const        fallthrough  if           range        type
continue     for          import       return       var

Miễn là bạn tuân thủ ba quy tắc đó, bất kỳ tên định danh nào cũng hợp lệ về mặt kỹ thuật và mã của bạn sẽ biên dịch tất cả OK. Nhưng có một loạt các hướng dẫn khác mà bạn nên tuân theo:

  • Bạn nên sử dụng camelCase cho số nhận dạng chưa xuất hoặc PascalCase cho số nhận dạng đã xuất. Không sử dụng các biến thể vỏ thay thế như snake_case, Pascal_Snake_Case, SCREAMING_SNAKE_CASE hoặc ALLUPPERCASE.

  • Các từ viết tắt hoặc viết tắt (như API, URL hoặc http) nên sử dụng một trường hợp nhất quán trong định danh. Vì vậy, ví dụ, apiKey hoặc APIKey là thông thường, nhưng ApiKey thì không. Quy tắc này cũng áp dụng cho ID khi nó được sử dụng làm tốc ký cho các từ "nhận dạng" hoặc "định danh" — nghĩa là ghi userID thay vì userId.

  • Mặc dù tất cả các chữ cái unicode đều được cho phép, nhưng việc sử dụng các chữ cái không phải ASCII thường có thể khiến mã của bạn khó đọc hơn và khó viết hơn, và rất hiếm khi thấy chúng được sử dụng. Trừ khi bạn có một trường hợp sử dụng thực sự thích hợp, bạn nên sử dụng các chữ cái ASCII trong số nhận dạng. Ví dụ: sử dụng pi thay vì π, sử dụng beta thay vì β, sử dụng naiveBayes thay vì naïveBayes.

  • Để tránh nhầm lẫn cho người đọc và các lỗi tiềm ẩn, tránh chọn số nhận dạng xung đột với Go's loại tích hợp. Vì vậy, ví dụ, không tạo các biến có tên như int, bool hoặc bất kỳ. Tương tự, tránh tạo các hàm có tên xung đột với các hàm tích hợp của Go. Vì vậy, ví dụ: không tạo các hàm có tên như min, max, len hoặc clear.

  • Nói chung, tránh đưa loại vào số nhận dạng — ví dụ: không sử dụng các tên như fullNameString, scoreInt hoặc float64Amount. Ngoại lệ chính cho điều này là khi bạn phải chuyển đổi một biến sang một loại khác và bạn muốn phân biệt giữa biến ban đầu và biến có chứa giá trị được chuyển đổi. Trong tình huống này, bao gồm cả loại trong định danh là một cách phổ biến và chấp nhận được để phân biệt giữa hai loại. Ví dụ: mã như thế này là OK:

    userID := 42
    userIDStr := strconv.Itoa(userID)
    
  • Nếu có thể, hãy cố gắng tránh chọn các mã định danh xung đột với tên gói thư viện tiêu chuẩn. Đây là một quy ước 'mềm hơn' so với các quy ước khác vì thư viện tiêu chuẩn đánh cắp rất nhiều tên định danh tốt — chẳng hạn như json, js, mail, user, csv, path, filepath, log, regexp, timeurl — và đôi khi có thể khó đưa ra các lựa chọn thay thế hợp lý. Tuy nhiên, bạn chắc chắn nên tránh tạo các mã định danh xung đột với tên gói mà mã của bạn đang thực sự nhập và sử dụng. Vì vậy, ví dụ: nếu bạn đang viết mã nhập khẩu url và gói net/mail, thì đừng sử dụng các từ urlmail làm định danh trong mã đó.

Dưới đây là một vài ví dụ về tên mã định danh tốt và xấu:

Tệ Lý do Tốt hơn
order.total := 99.99
func load-user()
Không cho phép dấu chấm câu orderTotal := 99.99
func loadUser()
const 3rdParty = "x"
func 2FactorAuth()
Không thể bắt đầu bằng một chữ số const thirdParty = "x"
func twoFactorAuth()
max_value := 10
func Fetch_user()
Vỏ bọc không đạt tiêu chuẩn maxValue := 10
func FetchUser()
loại HttpClient struct{}
func parseXml()
Vỏ chữ viết tắt không nhất quán loại HTTPClient struct{}
func parseXML()
func GetSessionId()
loại OrderId string
Giấy tờ tùy thân phải là tất cả các chữ hoa func GetSessionID()
loại Chuỗi ID thứ tự
sơ yếu lý lịch:= 2
const Σ = 100
Các chữ cái không phải ASCII resumeCount := 2
const sum = 100
func clear()
int := cache.Internal()
Xung đột với các loại hoặc chức năng tích hợp func clearQueue()
data := cache.Internal()
intCount := 42
resultSlice := []int{}
Loại có trong tên count := 42
kết quả := []int{}
kiểu json struct{}
var log = newLogger()
Xung đột với tên gói stdlib loại tải trọng cấu trúc{}
var logger = newLogger()

Số nhận dạng đã xuất và chưa xuất

Mã định danh trong cờ vây phân biệt chữ hoa chữ thường. Ví dụ: các số nhận dạng apiKey, apikey và APIKey đều khác nhau.

Như bạn có thể đã biết, khi một mã định danh bắt đầu bằng một chữ in hoa, nó sẽ được xuất — nghĩa là mã sẽ hiển thị bên ngoài gói mà nó được khai báo. Điều này có nghĩa là vỏ của chữ cái đầu tiên là đáng kể. Nó ảnh hưởng đến hành vi của cơ sở mã của bạn. Đổi lại, điều này có nghĩa là bạn không nên bắt đầu định danh bằng chữ in hoa chỉ vì chúng trông đẹp mắt — bạn chỉ nên bắt đầu chúng bằng chữ in hoa nếu bạn muốn chúng được xuất và có thể truy cập để mã bên ngoài gói mà chúng được khai báo.

Như một mẹo, hãy thử viết các gói bằng cách sử dụng mã định danh chưa được xuất theo mặc định. Chỉ xuất chúng khi bạn thực sự có nhu cầu.

Thông thường, bạn xuất càng ít, việc cấu trúc lại mã trong một gói càng dễ dàng mà không ảnh hưởng đến các phần khác trong cơ sở mã của bạn. Có một trích dẫn hay từ The Pragmatic Programmer, mà tôi sẽ điều chỉnh một chút cho danh pháp Go:

Viết mã nhút nhát - các gói không tiết lộ bất cứ điều gì không cần thiết cho các gói khác và không dựa vào các triển khai của các gói khác.

Mẹo thứ hai là rất hiếm khi một gói hàng chính được nhập bằng bất cứ thứ gì, vì vậy các mã định danh trong đó thường không được xuất và bắt đầu bằng chữ thường. Ngoại lệ thường gặp nhất là khi bạn cần xuất trường cấu trúc để hiển thị cho các gói sử dụng phản chiếu để hoạt động, như encoding/json, encoding/gob hoặc github.com/jmoiron/sqlx.

Độ dài và tính mô tả của bộ định danh

Nói chung, một mã định danh được sử dụng càng xa nơi nó được khai báo, tên càng mang tính mô tả.

Nếu bạn có một mã định danh có phạm vi hẹp và chỉ được sử dụng gần nơi nó được khai báo, bạn thường có thể sử dụng một tên ngắn và không mang tính mô tả. Ví dụ: nếu bạn đang đặt tên cho thứ gì đó chỉ được sử dụng trong một vòng lặp for nhỏ, khối phạm vi hoặc hàm rất ngắn, thì việc sử dụng tên ngắn hoặc thậm chí một chữ cái là rất phổ biến trong Go.

Nhưng nếu bạn đang đặt tên cho một cái gì đó có phạm vi lớn hơn hoặc được sử dụng cách xa nơi nó được khai báo, bạn nên sử dụng một cái tên mô tả rõ ràng những gì nó đại diện.

Dưới đây là một ví dụ tốt đẹp mà Dave Cheney đã đưa ra như là một phần của bài thuyết trình Thực hành của mình:

 loại Person struct {
Name string
    Age  int
}
func AverageAge(people []Person) int {
if len(people) == 0 {
return 0
}
    var count, sum int
    for _, p := range people {
sum += p.Age
        count += 1
}
    return sum / count
}

Trong mã này, trong khối phạm vi ngắn, chúng tôi sử dụng mã định danh p để đại diện cho một giá trị trong người slice — khối phạm vi quá nhỏ và chặt đến nỗi chỉ cần sử dụng một tên chữ cái là đủ rõ ràng.

Ngược lại, các biến countsum được khai báo, sau đó được sử dụng trong phạm vi, sau đó một lần nữa trong câu lệnh return. Cung cấp cho họ những cái tên mô tả rõ ràng hơn ngay lập tức những gì mã đang làm và những gì chúng đại diện, so với các tên chữ cái đơn lẻ như cs. Nhưng các biến này chỉ được sử dụng bên trong hàm AverageAge, vì vậy việc đặt cho chúng những cái tên thậm chí nhiều mô tả hơn như peopleCount và agesSum sẽ không cần thiết.

Nó không phải là một khoa học chính xác, nhưng khi viết mã Go, bạn được khuyến khích sử dụng định danh độ dài phù hợp — đôi khi có thể dài và mô tả, đôi khi nó có thể ngắn gọn và ngắn gọn.

Gói đặt tên

Các quy tắc cứng cho tên gói giống như đối với số nhận dạng: chúng có thể chứa các chữ cái unicode, số và dấu gạch dưới, không được bắt đầu bằng một số và không được là từ khóa Go. Nhưng trên thực tế, các quy ước để đặt tên cho một gói hàng chặt chẽ hơn nhiều. Thông thường:

  • Tên gói chỉ được chứa chữ cái và số ASCII thường.

  • Bởi vì tên gói sẽ cần phải được gõ ra rất nhiều khi viết mã, tên lý tưởng nên ngắn gọn, dễ gõ và phản ánh nội dung của gói. Thông thường các danh từ một từ đơn giản (như đơn đặt hàng, khách hàngcon sên) hoạt động tốt.

  • Nếu bạn muốn sử dụng nhiều hơn một từ trong tên gói, bạn nên nối tất cả các từ bằng chữ thường mà không có dấu phân cách. Vì vậy, ví dụ, người quản lý đơn hàng là một tên gói thông thườngorderManager hoặc order_manager thì không.

  • Nếu tên gói cảm thấy quá dài, bạn có thể sử dụng chữ viết tắt trong tên. Bạn có thể thấy điều này trong một số tên gói thư viện tiêu chuẩn, như expvar (thay exportvariables) strconv (thay vì stringconversion).

  • Để tránh xung đột và nhầm lẫn, hãy cố gắng tránh sử dụng cùng tên với các gói thư viện tiêu chuẩn thường được sử dụng.

  • Tên gói có tiền tố. or _ là 'vô hình' để đi và hoàn toàn bị bỏ qua khi bạn chạy đi xây dựng, đi chạy, đi kiểm tra, v.v. Vì vậy, đừng bắt đầu tên gói của bạn với những ký tự này, trừ khi bạn đặc biệt muốn chúng bị bỏ qua.

  • Thư mục có tên nhà cung cấp, testdatanội bộ có một ý nghĩa đặc biệt trong cờ vây, vì vậy để tránh bất kỳ sự nhầm lẫn hoặc lỗi nào, đừng sử dụng những từ này làm tên gói.

  • Tránh sử dụng các tên gói 'catch all' như common, util, helpers, types hoặc interfaces, những tên này không thực sự cung cấp bất kỳ manh mối nào về nội dung của gói. Ví dụ: gói được gọi là người trợ giúp có chứa người trợ giúp xác thực, người trợ giúp định dạng, người trợ giúp SQL không? Một sự kết hợp của tất cả những điều trên? Bạn không thể đoán được chỉ từ cái tên. Cũng như không rõ ràng, những cái tên 'bắt tất cả' này cung cấp rất ít ranh giới hoặc phạm vi tự nhiên, điều này có thể dẫn đến việc gói hàng trở thành bãi rác cho nhiều thứ khác nhau. Đổi lại, gói có thể được nhập và sử dụng trong toàn bộ cơ sở mã của bạn — điều này làm tăng nguy cơ chu kỳ nhập và có nghĩa là những thay đổi đối với gói có khả năng ảnh hưởng đến toàn bộ cơ sở mã, thay vì chỉ một phần cụ thể của nó. Nói cách khác, bắt tất cả các tên gói khuyến khích tạo các gói có 'bán kính nổ' lớn. Nếu bạn thấy mình muốn tạo một gói đồ dùng hoặc trợ giúp, hãy tự hỏi liệu bạn có thể chia nhỏ nội dung thành các gói nhỏ hơn với trọng tâm cụ thể và tên rõ ràng hơn không.

Đặt tên tệp

Trong thế giới lý tưởng, tên tệp .go phải tóm tắt nội dung tệp chứa, dài một từ và tất cả đều bằng chữ thường. Một số ví dụ về tên tệp tốt từ gói net/http thư viện tiêu chuẩn là cookie.go, server.gostatus.go.

Nếu bạn không thể nghĩ ra một cái tên hay gồm một từ và muốn sử dụng hai từ trở lên thì không có quy ước rõ ràng nào về cách phân tách các từ đó. Ngay cả trong thư viện chuẩn của Go cũng không có sự nhất quán. Đôi khi, dấu gạch dưới được sử dụng để phân tách các từ trong tên tệp (như routing_index.gorouting_tree.go) và đôi khi chúng được nối mà không nối gì giữa chúng (như batchcursor.go, textreader.goreverseproxy.go).

Vì không có quy ước rõ ràng về vấn đề này nên tôi khuyên bạn chỉ nên chọn một trong hai cách tiếp cận này và tuân thủ nó một cách nhất quán trong một cơ sở mã. Cá nhân tôi nghĩ sẽ tốt hơn nếu nối các từ không có gì ở giữa chúng (như routingindex.go) và chỉ dành ký tự gạch dưới khi bạn muốn sử dụng hậu tố tên tệp đặc biệt.

Nói về điều này, có một số tiền tố và hậu tố của tên tệp có ý nghĩa đặc biệt trong Go. Bạn nên tránh sử dụng những tên này trong tên tệp của mình trừ khi bạn muốn kích hoạt hành vi đặc biệt. Cụ thể:

  • Giống như các gói, tên tệp có tiền tố . hoặc _ là 'vô hình' đối với công cụ Go và hoàn toàn bị bỏ qua khi bạn chạy go build, go run, go test, v.v.

  • Các tệp có hậu tố _test.go chỉ được chạy bằng công cụ go test. Chúng bị bỏ qua khi sử dụng go run hoặc go build.

  • Các tệp có bất kỳ hậu tố nào sau đây sẽ chỉ được đưa vào khi biên dịch cho hệ điều hành cụ thể đó: _aix.go, _android.go, _darwin.go, _dragonfly.go, _freebsd.go, _illumos.go, _ios.go, _js.go, _linux.go, _netbsd.go , _openbsd.go, _plan9.go, _solaris.go, _wasip1.go, _windows.go.

  • Tương tự, các tệp có bất kỳ hậu tố nào sau đây sẽ chỉ được đưa vào khi biên dịch cho kiến trúc cụ thể đó: _386.go, _amd64.go, _arm.go, _arm64.go, _loong64.go, _mips.go, _mips64.go, _mips64le.go, _mipsle.go, _ppc64.go, _ppc64le.go, _riscv64.go, _s390x.go, _wasm.go.

Tránh nói nhảm

Khi bạn đặt tên cho các hàm đã xuất, hãy cố gắng tránh lặp lại tên của gói mà chúng được khai báo.

Ví dụ: nếu bạn có gói có tên là customer thì các tên hàm như NewCustomer() hoặc CustomerOrders() sẽ là 'nói nhảm' và lặp lại từ 'khách hàng' một cách không cần thiết khi bạn gọi họ từ bên ngoài gói — như customer.NewCustomer()customer.CustomerOrders(). Gọi các hàm New()Orders() là đủ và đọc tốt hơn tại trang cuộc gọi — như customer.New()customer.Orders().

Lời khuyên tương tự cũng áp dụng cho các loại được xuất. Ví dụ: nếu bạn muốn thể hiện một địa chỉ hoặc số điện thoại trong gói khách hàng, việc đặt tên cho các loại Địa chỉPhoneNumber thay vì CustomerAddressCustomerPhoneNumber là đủ và ít rườm rà hơn.

<đầu>

Tương tự như tên hàm và tên kiểu, lý tưởng nhất là tên phương thức không nên gây 'lộn xộn' quá nhiều khi gọi chúng. Ví dụ: nếu bạn đang viết phương thức trên loại Token, bạn có thể gọi phương thức Validate() thay vì ValidateToken() hoặc IsExpired() thay vì IsTokenExpired().

Bộ nhận phương thức

Khi bạn tạo phương thức, thông thường phương thức receiver phải có tên ngắn, thường dài từ 1 đến 3 ký tự và thường là tên viết tắt của loại mà phương thức được triển khai. Ví dụ: nếu bạn đang triển khai một phương thức trên loại Khách hàng, tên người nhận thành ngữ sẽ giống như c hoặc cus. Hoặc nếu bạn đang triển khai một phương thức trên loại HighScore thì tên bộ thu phù hợp sẽ là hs.

Nhận xét đánh giá mã Go lời khuyên không nên sử dụng các tên chung chung như this, self hoặc me cho người nhận.

Ngoài ra, bạn phải nhất quán với tên người nhận. Tất cả các phương thức trên cùng loại phải sử dụng cùng tên người nhận — không sử dụng c cho một phương thức và cus cho phương thức khác.

 gõ Cấu trúc đơn hàng {
    Mục int
}
// Tốt: sử dụng bộ thu ngắn 
func (o *Order) Xác thực() bool {
    trả về o.Items > 0
}
// Xấu: sử dụng tên người nhận dài hơn
func (đặt hàng *Đặt hàng) Xác thực() bool {
    trả lại đơn hàng.Các mặt hàng > 0
}
// Xấu: sử dụng tên người nhận chung
func (self *Order) Xác thực() bool {
    tự trả về.Items> 0
}

Phương thức getter và setter trên cấu trúc

Thông thường, không cần thiết phải tạo phương thức 'getter' và 'setter' trên các kiểu cấu trúc trong Go. Thay vào đó, bạn chỉ cần truy cập trực tiếp vào trường struct để đọc hoặc thay đổi dữ liệu. Ngoại lệ chính cho trường hợp này là khi bạn có một cấu trúc với trường chưa được xuất nhưng muốn cung cấp cách lấy hoặc đặt giá trị trường từ bên ngoài gói. Để thực hiện việc này, bạn cần tạo các phương thức 'getter' và 'setter' đã xuất để đọc và ghi vào trường chưa xuất.

Khi thực hiện việc này, thông thường là thêm Set vào trước tên phương thức setter, nhưng không đặt tiền tố Get vào tên phương thức getter. Giống như vậy:

loại Cấu trúc khách hàng {
    chuỗi địa chỉ
}
chuỗi func (c *Khách hàng) Địa chỉ() {
    trả lại c.địa chỉ
}
func (c *Khách hàng) SetAddress(chuỗi addr) {
    c.địa chỉ = addr
}

Giao diện

Theo quy ước, các giao diện chỉ chứa một phương thức phải được đặt tên theo tên phương thức cộng với hậu tố '-er' hoặc tương tự. Ví dụ:

loại Giao diện loa {
    Chuỗi Speak()
}
gõ Giao diện ủy quyền {
    Lỗi ủy quyền (ctx context.Context, chuỗi hành động)
}
gõ giao diện Authenticator {
    Xác thực(ctx context.Context) (Người dùng, lỗi)
}

Thư viện chuẩn của Go có khá nhiều ví dụ về giao diện tuân theo quy ước này, chẳng hạn như io.Reader, io.Writerfmt.Stringer (và một số, như http.Handler, không có).

Cũng lưu ý rằng hướng dẫn tránh đưa loại vào tên vẫn áp dụng cho giao diện. Đừng đặt tên cho giao diện của bạn như UserInterface hoặc OrderInterface trừ khi bạn thực sự không thể nghĩ ra một giải pháp thay thế phù hợp.

Phá vỡ quy ước

Trong một số trường hợp hiếm hoi, việc phá vỡ một quy ước thực sự có thể làm cho mã của bạn rõ ràng hơn — và theo quan điểm của tôi, bạn có thể làm điều đó... đặc biệt nếu mã đó nằm trong một cơ sở mã riêng do một nhóm nhỏ làm việc.

Ví dụ: vài năm trước, tôi đang làm việc trên một chương trình Go nhằm đồng bộ hóa dữ liệu giữa một số hệ thống bên ngoài khác. Trong dự án này, tôi đã phá vỡ một số quy ước đặt tên Go xung quanh vỏ và dấu phân cách — thay vào đó sử dụng chính xác các mã định danh giống nhau mà các hệ thống bên ngoài đã sử dụng. Điều này thực sự làm cho mục đích của chương trình trở nên rõ ràng hơn và rõ ràng hơn ngay lập tức những gì đang được đồng bộ hóa với những gì.

Nhưng trong phần lớn trường hợp, bạn nên cố gắng tuân theo các quy tắc và quy ước đặt tên mà chúng ta đã thảo luận trong bài đăng này. Chúng tồn tại vì những lý do chính đáng: chúng làm cho mã của bạn dễ dự đoán và nhất quán hơn, giúp các Gopher khác dễ dàng hiểu nhanh hơn và giảm nguy cơ mắc một số lỗi nhất định.

Tác giả: yurivish

#discussion
T
TeckieGURU

© 2026 Teckie GURU — Tin tức công nghệ cho developer Việt

Built with Strapi, Next.js & AI Translation

Tệ Lý do Tốt hơn
gói bên thứ
3 gói 2fa
Không thể bắt đầu bằng chữ số gói bên thứ ba
gói twofa
trình quản lý đơn hàng gói
gói order_manager
Vỏ / dải phân cách không chuẩn người quản lý đơn hàng gói
gói o
thứ trong gói
Quá mơ hồ và không có tính mô tả đơn đặt hàng trọn gói
sên gói
hệ thống quản lý đơn hàng gói Quá dài / khó gõ đơn đặt hàng trọn gói
đơn đặt hàng gói
url gói
thư gói
Xung đột với tên gói stdlib liên kết gói
người gửi gói hàng
gói _cache
gói .hidden
Bỏ qua công cụ Go bộ đệm gói
gói bị ẩn
nội bộ gói
nhà cung cấp gói
dữ liệu kiểm tra gói
Tên thư mục đặc biệt trong Go gói nội bộauth
nhà cung cấp gói
tiện ích gói
trình trợ giúp gói
Bắt tất cả các tên có phạm vi không rõ ràng xác thực gói
định dạng gói
Xấu Lý do Tốt hơn
customer.NewCustomer()
customer.CustomerOrders()
Gọi hàm trò chuyện customer.New()
customer.Orders()
customer.CustomerAddress
customer.CustomerPhoneNumber
Tham chiếu loại trò chuyện customer.Address
customer.PhoneNumber