Source: https://go.dev/doc/effective_go
gofmt to automatically format your codeExample:
// Package regexp implements regular expression search.
package regexp
// Compile parses a regular expression and returns, if successful,
// a Regexp object that can be used to match against text.
func Compile(str string) (*Regexp, error) {
bytes.Buffer not bytes.ByteBuffer)Owner() not GetOwner()SetOwner()Reader, Writer, Formatter, CloseNotifierMixedCaps or mixedCaps rather than underscoresif err := file.Chmod(0664); err != nil {
log.Print(err)
return err
}
f, err := os.Open(name)
// err is declared here
d, err := f.Stat()
// err is redeclared here (same scope)
// Like a C for
for init; condition; post { }
// Like a C while
for condition { }
// Like a C for(;;)
for { }
// Range over array/slice/map/channel
for key, value := range oldMap {
newMap[key] = value
}
// If you only need the key
for key := range m {
// ...
}
// If you only need the value
for _, value := range array {
// ...
}
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
switch t := value.(type) {
case int:
fmt.Printf("int: %d\n", t)
case string:
fmt.Printf("string: %s\n", t)
default:
fmt.Printf("unexpected type %T\n", t)
}
func (file *File) Write(b []byte) (n int, err error) {
// ...
}
func ReadFull(r Reader, buf []byte) (n int, err error) {
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[nr:]
}
return
}
func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
new(T) allocates zeroed storage for new item of type T*Tp := new(int) // p is *int, points to zeroed int
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
return &File{fd: fd, name: name}
}
make(T, args) creates slices, maps, and channels onlymake([]int, 10, 100) // slice: len=10, cap=100
make(map[string]int) // map
make(chan int, 10) // buffered channel
appendnil%v - default format%+v - struct with field names%#v - Go syntax representation%T - type%q - quoted stringinit() functionfunc init() {
// initialization code
}
Rule: Value methods can be called on both values and pointers, but pointer methods should only be called on pointers (though Go allows calling on addressable values).
type ByteSlice []byte
func (slice ByteSlice) Append(data []byte) []byte {
// ...
}
func (p *ByteSlice) Append(data []byte) {
slice := *p
// ...
*p = slice
}
value, ok := str.(string)
switch v := value.(type) {
case string:
// v is string
case int:
// v is int
}
import _ "net/http/pprof" // Import for side effects
var _ json.Marshaler = (*RawMessage)(nil)
type ReadWriter struct {
*Reader // *bufio.Reader
*Writer // *bufio.Writer
}
go keywordmakeci := make(chan int) // unbuffered
cj := make(chan int, 0) // unbuffered
cs := make(chan *os.File, 100) // buffered
type Request struct {
args []int
f func([]int) int
resultChan chan int
}
const numCPU = runtime.NumCPU()
runtime.GOMAXPROCS(numCPU)
type error interface {
Error() string
}
type PathError struct {
Op string
Path string
Err error
}
func (e *PathError) Error() string {
return e.Op + " " + e.Path + ": " + e.Err.Error()
}
func server(workChan <-chan *Work) {
for work := range workChan {
go safelyDo(work)
}
}
func safelyDo(work *Work) {
defer func() {
if err := recover(); err != nil {
log.Println("work failed:", err)
}
}()
do(work)
}
package main
import (
"fmt"
"log"
"net/http"
)
type Counter struct {
n int
}
func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctr.n++
fmt.Fprintf(w, "counter = %d\n", ctr.n)
}
func main() {
ctr := new(Counter)
http.Handle("/counter", ctr)
log.Fatal(http.ListenAndServe(":8080", nil))
}