当前位置:网站首页>Go language programming specification combing summary
Go language programming specification combing summary
2022-07-05 15:27:00 【dnice】
This article summarizes 20 strip go Language programming experience , The reference link is at the end of the article , Interested friends can check .
1. Standardize and uniformly define package, Avoid circular dependencies
go Circular dependencies are not supported , So we're going to be here package Make more efforts in design , Avoid circular dependency in multi person collaborative development .
2. Avoid lines of code that are too long
The threshold of single line code can be uniformly Limited ,uber_go_guide It is suggested to limit the president to 99 Characters , But no rigid restrictions , This limit can be exceeded .
3. Similar statements are placed in a group
Go Language support puts similar statements in a group .
import "a"
import "b"
import (
"a"
"b"
)
This also applies to constants 、 Variable and type declaration :
const a = 1
const b = 2
var a = 1
var b = 2
type Area float64
type Volume float64
const (
a = 1
b = 2
)
var (
a = 1
b = 2
)
type (
Area float64
Volume float64
)
Put only the relevant statements in a group . Don't put irrelevant statements in a group .
type Operation int
const (
Add Operation = iota + 1
Subtract
Multiply
EnvVar = "MY_ENV"
)
type Operation int
const (
Add Operation = iota + 1
Subtract
Multiply
)
const EnvVar = "MY_ENV"
There is no limit to where groups can be used , for example : You can use them inside functions :
func f() string {
red := color.New(0xff0000)
green := color.New(0x00ff00)
blue := color.New(0x0000ff)
...
}
func f() string {
var (
red = color.New(0xff0000)
green = color.New(0x00ff00)
blue = color.New(0x0000ff)
)
...
}
4.import grouping
import Should be divided into two groups :
- Standard library
- Other libraries
import (
"fmt"
"os"
"go.uber.org/atomic"
"golang.org/x/sync/errgroup"
)
import (
"fmt"
"os"
"go.uber.org/atomic"
"golang.org/x/sync/errgroup"
)
5. Package name
When naming a package , Please select a name according to the following rules :
- All lowercase . No capitals or underscores .
- In most cases where named imports are used , No need to rename .
- Short and concise .
- Don't use the plural . for example net/url, instead of net/urls.
- Do not use “common”,“util”,“shared” or “lib”. These are not good , Names with insufficient information .
6. Function name
follow Go Community Convention on using hump naming as function name . There is one exception , To group related test cases , Function names may contain underscores , Such as :TestMyFunction_WhatIsBeingTested.
7. Import alias
In two cases, you need to use the import alias , Otherwise, you should avoid using import aliases .
- If the package name does not match the last element of the import path , You must use the import alias .
import (
"net/http"
client "example.com/client-go"
trace "example.com/trace/v2"
)
- When there is a direct conflict between importing multiple package names , Import alias should be used .
import (
"fmt"
"os"
nettrace "golang.net/x/trace"
)
import (
"fmt"
"os"
"runtime/trace"
nettrace "golang.net/x/trace"
)
8. Function grouping and order
- Functions should be sorted in rough order of call .
- Functions in the same file should be grouped by recipients .
9. Reduce the nested
The code should deal with error situations as early as possible / Special case and return or continue loop as early as possible to reduce nesting . Reduce the amount of code nesting multiple levels of code .
for _, v := range data {
if v.F1 == 1 {
v = process(v)
if err := v.Call(); err == nil {
v.Send()
} else {
return err
}
} else {
log.Printf("Invalid v: %v", v)
}
}
for _, v := range data {
if v.F1 != 1 {
log.Printf("Invalid v: %v", v)
continue
}
v = process(v)
if err := v.Call(); err != nil {
return err
}
v.Send()
}
10. Reduce unnecessary else
If in if Variables are set in both branches of , You can replace it with a single if.
var a int
if b {
a = 100
} else {
a = 10
}
a := 10
if b {
a = 100
}
11. Top level variable declaration
On the top floor , Use standards var keyword . Do not specify type , Unless it's different from the type of expression .
var _s string = F()
func F() string {
return "A" }
var _s = F()
// because F You've made it clear to return a string type , So we don't need to explicitly specify _s The type of
// It's the same type
func F() string {
return "A" }
If the type of the expression does not exactly match the expected type , Please specify the type .
type myError struct{
}
func (myError) Error() string {
return "error" }
func F() myError {
return myError{
} }
var _e error = F()
// F Return to one myError Instance of type , But we have to error type
12. Local variable declaration
If the variable is explicitly set to a value , You should use the short variable declaration form (:=).
var s = "foo"
s := "foo"
however , In some cases ,var The default values are clearer when using keywords . for example , Declare empty slices .
func f(list []int) {
filtered := []int{
}
for _, v := range list {
if v > 10 {
filtered = append(filtered, v)
}
}
}
func f(list []int) {
var filtered []int
for _, v := range list {
if v > 10 {
filtered = append(filtered, v)
}
}
}
13.nil Is an effective slice
nil Is an effective length for 0 Of slice, It means :
- Return should be used nil Instead of returning slices with zero length .
if x == "" {
return []int{
}
}
if x == "" {
return nil
}
- To check if the slice is empty , Please always use len(s) == 0. Instead of nil.
func isEmpty(s []string) bool {
return s == nil
}
func isEmpty(s []string) bool {
return len(s) == 0
}
- Zero slice ( use var Slice of the declaration ) It can be used immediately , Don't need to call make() establish .
nums := []int{
}
// or, nums := make([]int)
if add1 {
nums = append(nums, 1)
}
if add2 {
nums = append(nums, 2)
}
var nums []int
if add1 {
nums = append(nums, 1)
}
if add2 {
nums = append(nums, 2)
}
Be careful : although nil Slice is a valid slice , But it is not equal to the length 0 The section of ( One for nil, The other is not ), And in different situations ( For example, serialization ), These two slices may be processed differently .
14. Avoid ambiguous parameter semantics
Ambiguous parameters in function calls can damage readability . When the meaning of the parameter name is not obvious , Please add C Style notes (/* … */)
// func printInfo(name string, isLocal, done bool)
printInfo("foo", true, true)
// func printInfo(name string, isLocal, done bool)
printInfo("foo", true /* isLocal */, true /* done */)
For the example code above , There is a better way to deal with it bool Type to custom type . future , This parameter can support more than two states (true/false).
type Region int
const (
UnknownRegion Region = iota
Local
)
type Status int
const (
StatusReady Status= iota + 1
StatusDone
// Maybe we will have a StatusInProgress in the future.
)
func printInfo(name string, region Region, status Status)
15. Use the original string literal , Avoid escaping
Go Support use Original string literal , That is to say " ` " To represent a native string , In the situation where escape is needed , We should try to use this scheme to replace .
Can span multiple lines and include quotes . Using these strings can avoid manually escaping strings that are more difficult to read .
wantError := "unknown name:\"test\""
wantError := `unknown error:"test"`
16. Initialize structure
- Initialize the structure with the field name
When initializing structure , You should almost always specify a field name .
k := User{
"John", "Doe", true}
k := User{
FirstName: "John",
LastName: "Doe",
Admin: true,
}
exception : When there is 3 When there are two or fewer fields , The field names in the test table can be omitted .
tests := []struct{
op Operation
want string
}{
{
Add, "add"},
{
Subtract, "subtract"},
}
- Omit the zero value field in the structure
When initializing a structure with a field name , Unless a meaningful context is provided , Otherwise, fields with zero values are ignored . That is to say , Let's automatically set these to zero .
user := User{
FirstName: "John",
LastName: "Doe",
MiddleName: "",
Admin: false,
}
user := User{
FirstName: "John",
LastName: "Doe",
}
This helps reduce dyslexia by omitting default values in this context . Specify only meaningful values .
- Use... For zero valued structures var
If you omit all the fields of the structure in the declaration , Please use var Declaration structure .
user := User{
}
var user User
- initialization Struct quote
When initializing a structure reference , Please use &T{} Instead of new(T), To make it consistent with struct initialization .
sval := T{
Name: "foo"}
// inconsistent
sptr := new(T)
sptr.Name = "bar"
sval := T{
Name: "foo"}
sptr := &T{
Name: "bar"}
17. Specify the container capacity
Specify the container capacity as much as possible , To pre allocate memory for the container . This will minimize subsequent allocations when adding elements ( By copying and resizing containers ).
- Appoint Map Capacity prompt
As far as possible , In the use of make() Provide capacity information during initialization
make(map[T1]T2, hint)
towards make() Provide the capacity prompt and try to adjust it during initialization map Size , This will reduce the number of elements added to map When is map Reallocate memory .
Be careful , And slices Different .map capacity Prompt does not guarantee full preemptive allocation , It is used to estimate the required hashmap bucket The number of . therefore , Adding elements to map when , Even when specifying map Capacity time , Allocation may still occur .
m := make(map[string]os.FileInfo)
files, _ := ioutil.ReadDir("./files")
for _, f := range files {
m[f.Name()] = f
}
// m It was created without a size hint ; There may be more assignments at run time .
files, _ := ioutil.ReadDir("./files")
m := make(map[string]os.FileInfo, len(files))
for _, f := range files {
m[f.Name()] = f
}
// m It's created with size hints ; There may be fewer assignments at run time .
- Specify slice capacity
As far as possible , In the use of make() Provide capacity information when initializing slices , Especially when adding slices .
make([]T, length, capacity)
And maps Different ,slice capacity Not a hint : The compiler will provide to make() Of slice Allocate enough memory , This means subsequent append()` Operation will result in zero allocation ( until slice The length of the matches the capacity , After that , whatever append Can be resized to accommodate other elements ).
for n := 0; n < b.N; n++ {
data := make([]int, 0)
for k := 0; k < size; k++{
data = append(data, k)
}
}
BenchmarkBad-4 100000000 2.48s
for n := 0; n < b.N; n++ {
data := make([]int, 0, size)
for k := 0; k < size; k++{
data = append(data, k)
}
}
BenchmarkGood-4 100000000 0.21s
18. priority of use strconv instead of fmt
When converting primitives to or from strings ,strconv Velocity ratio fmt fast .
for i := 0; i < b.N; i++ {
s := fmt.Sprint(rand.Int())
}
BenchmarkFmtSprint-4 143 ns/op 2 allocs/op
for i := 0; i < b.N; i++ {
s := strconv.Itoa(rand.Int())
}
BenchmarkStrconv-4 64.2 ns/op 1 allocs/op
19. Avoid string to byte conversion
Do not repeatedly create bytes from fixed strings slice. contrary , Please perform a conversion and capture the results .
for i := 0; i < b.N; i++ {
w.Write([]byte("Hello world"))
}
BenchmarkBad-4 50000000 22.2 ns/op
data := []byte("Hello world")
for i := 0; i < b.N; i++ {
w.Write(data)
}
BenchmarkGood-4 500000000 3.25 ns/op
20. character string string format
If you declare outside the function Printf-style The format string of the function , Please set it to const Constant .
This helps go vet Perform static analysis of format strings .
msg := "unexpected values %v, %v\n"
fmt.Printf(msg, 1, 2)
const msg = "unexpected values %v, %v\n"
fmt.Printf(msg, 1, 2)
Reference link
Reference links for this article :https://github.com/uber-go/guide/blob/master/style.md
边栏推荐
- Optional parameters in the for loop
- SQL Server learning notes
- Surpass palm! Peking University Master proposed diverse to comprehensively refresh the NLP reasoning ranking
- 把 ”中台“ 的思想迁移到代码中去
- Brief introduction of machine learning framework
- Common MySQL interview questions
- Magic methods and usage in PHP (PHP interview theory questions)
- Easyocr character recognition
- Bugku's Ping
- 华为哈勃化身硬科技IPO收割机
猜你喜欢
ionic cordova项目修改插件
Creation and use of thymeleaf template
Talk about your understanding of microservices (PHP interview theory question)
No one consults when doing research and does not communicate with students. UNC assistant professor has a two-year history of teaching struggle
Ionic Cordova project modification plug-in
P1451 calculate the number of cells / 1329: [example 8.2] cells
Good article inventory
Crud de MySQL
Bugku's Ah Da
Bugku cyberpunk
随机推荐
How can I quickly check whether there is an error after FreeSurfer runs Recon all—— Core command tail redirection
I spring and autumn blasting-1
Reasons and solutions for redis cache penetration and cache avalanche
keep-alive
Common redis data types and application scenarios
百亿按摩仪蓝海,难出巨头
Number protection AXB function! (essence)
Calculate weight and comprehensive score by R entropy weight method
swiper. JS to achieve barrage effect
ICML 2022 | explore the best architecture and training method of language model
String modification problem solving Report
Value series solution report
Ctfshow web entry command execution
DVWA range clearance tutorial
漫画:程序员不是修电脑的!
社区团购撤城“后遗症”
一文搞定vscode编写go程序
Severlet learning foundation
mapper. Comments in XML files
做研究无人咨询、与学生不交心,UNC助理教授两年教职挣扎史