当前位置:网站首页>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
边栏推荐
- Bubble sort, insert sort
- JS topic - console log()
- Creation and use of thymeleaf template
- Calculate weight and comprehensive score by R entropy weight method
- 一文搞定vscode编写go程序
- Live broadcast preview | how to implement Devops with automatic tools (welfare at the end of the article)
- Redis' transaction mechanism
- Your childhood happiness was contracted by it
- 【简记】解决IDE golang 代码飘红报错
- Number protection AXB function! (essence)
猜你喜欢

Ctfshow web entry command execution

lv_ font_ Conv offline conversion

Fr exercise topic - simple question

"Sequelae" of the withdrawal of community group purchase from the city
![P6183 [USACO10MAR] The Rock Game S](/img/f4/d8c8763c27385d759d117b515fbf0f.png)
P6183 [USACO10MAR] The Rock Game S

Transfer the idea of "Zhongtai" to the code

Good article inventory

Behind the ultra clear image quality of NBA Live Broadcast: an in-depth interpretation of Alibaba cloud video cloud "narrowband HD 2.0" technology

Bugku's steganography

Reasons and solutions for redis cache penetration and cache avalanche
随机推荐
[recruitment position] infrastructure software developer
Hongmeng system -- Analysis from the perspective of business
[JVM] operation instruction
Redis distributed lock principle and its implementation with PHP (1)
P1451 求细胞数量/1329:【例8.2】细胞
Bugku's eyes are not real
lvgl 显示图片示例
JS topic - console log()
MySQL----函数
MySQL5.7的JSON基本操作
可转债打新在哪里操作开户是更安全可靠的呢
Bugku's steganography
JS knowledge points-01
当代人的水焦虑:好水究竟在哪里?
go学习 ------jwt的相关知识
一文搞定vscode编写go程序
B站做短视频,学抖音死,学YouTube生?
Summary of the third class
美团优选管理层变动:老将刘薇调岗,前阿里高管加盟
sql server char nchar varchar和nvarchar的区别