// foo.go
package foo
type Config struct {
_ [0]int
Name string
Size int
}
// main.go
package main
import "foo"
func main() {
//_ = foo.Config{[0]int{}, "bar", 123} // error
_ = foo.Config{Name: "bar", Size: 123} // compile ok
}
package main
type T struct {
dummy [0]func()
AnotherField int
}
var x map[T]int // compile error: invalid map key type T
func main() {
var a, b T
_ = a == b // compile error: invalid operation:
}
[7 0 9]
, [0 8 9]
, or [7 8 9]
, depending on compiler implementations.
package main
import "fmt"
var a = &[]int{1, 2, 3}
var i int
func f() int {
i = 1
a = &[]int{7, 8, 9}
return 0
}
func main() {
// The evaluation order of "a", "i"
// and "f()" is unspecified.
(*a)[i] = f()
fmt.Println(*a)
}
for i in 0..N
in some other languages?
package main
import "fmt"
func main() {
const N = 5
for i := range [N]struct{}{} {
fmt.Println(i)
}
for i := range [N][0]int{} {
fmt.Println(i)
}
for i := range (*[N]int)(nil) {
fmt.Println(i)
}
}
bytes.Buffer
type, strings.Builder
type and the types in the sync
standard package are not recommended to be copied. (They really should not be copied, though it is no problems to copy them under some specified circumstances.)
strings.Builder
will detect invalid strings.Builder
value copies. Once such a copy is found, panic will occur. For example:
package main
import "strings"
func main() {
var b strings.Builder
b.WriteString("hello ")
var b2 = b
b2.WriteString("world!") // panic here
}
sync
standard package will be warned by the go vet
command provided in Go Toolchain.
// demo.go
package demo
import "sync"
func f(m sync.Mutex) { // warning
m.Lock()
defer m.Unlock()
// do something ...
}
$ go vet demo.go ./demo.go:5: f passes lock by value: sync.Mutex
bytes.Buffer
values will never be detected at run time nor by the go vet
command. Just be careful not to do this.
memclr
optimization for details.
reflect
package?
M(int) string
.)
package main
import "fmt"
type A int
type B int
func (b B) M(x int) string {
return fmt.Sprint(b, ": ", x)
}
func check(v interface{}) bool {
_, has := v.(interface{M(int) string})
return has
}
func main() {
var a A = 123
var b B = 789
fmt.Println(check(a)) // false
fmt.Println(check(b)) // true
}
func NewX(...Option) *X
function, and the implementation of this function will merge the input options with some internal default options, then the following implementation is not recommended.
func NewX(opts ...Option) *X {
options := append(opts, defaultOpts...)
// Use the merged options to build and return a X.
// ...
}
append
call may modify the underlying Option
sequence of the argument opts
. For most scenarios, it is not a problem. But for some special scenarios, it may cause some unexpected results.
Option
sequence of the input argument, we should use the following way instead.
func NewX(opts ...Option) *X {
opts = append(opts[:len(opts):len(opts)], defaultOpts...)
// Use the merged options to build and return a X.
// ...
}
NewX
function, it is not a good idea to think and rely on the NewX
function will not modify the underlying elements of the passed slice arguments, so it is best to pass these arguments with the three-index subslice form.
package myreader
import "io"
type MyReader uint16
func NewMyReader() *MyReader {
var mr MyReader
return &mr
}
func (mr *MyReader) Read(data []byte) (int, error) {
switch len(data) {
default:
*mr = MyReader(data[0]) << 8 | MyReader(data[1])
return 2, nil
case 2:
*mr = MyReader(data[0]) << 8 | MyReader(data[1])
case 1:
*mr = MyReader(data[0])
case 0:
}
return len(data), io.EOF
}
// Any of the following three lines ensures
// type *MyReader implements io.Reader.
var _ io.Reader = NewMyReader()
var _ io.Reader = (*MyReader)(nil)
func _() {_ = io.Reader(nil).(*MyReader)}
N
is not smaller than another constant M
at compile time:
// Any of the following lines can guarantee N >= M
func _(x []int) {_ = x[N-M]}
func _(){_ = []int{N-M: 0}}
func _([N-M]int){}
var _ [N-M]int
const _ uint = N-M
type _ [N-M]int
// If M and N are guaranteed to be positive integers.
var _ uint = N/M - 1
var _ = map[bool]struct{}{false: struct{}{}, N>=M: struct{}{}}
var _ = map[bool]int{false: 0, N>=M: 1}
var _ [N-M]int; var _ [M-N]int
type _ [N-M]int; type _ [M-N]int
const _, _ uint = N-M, M-N
func _([N-M]int, [M-N]int) {}
var _ = map[bool]int{false: 0, M==N: 1}
var _ = [1]int{M-N: 0} // the only valid index is 0
var _ = [1]int{}[M-N] // the only valid index is 0
var _ [N-M]int = [M-N]int{}
type _ [len(aStringConstant)-1]int
var _ = map[bool]int{false: 0, aStringConstant != "": 1}
var _ = aStringConstant[:1]
var _ = aStringConstant[0]
const _ = 1/len(aStringConstant)
func _() {
var _ = map[bool]int{false: 0, N>=M: 1}
var _ [N-M]int
}
const MaxUint = ^uint(0)
const MaxInt = int(^uint(0) >> 1)
const Is64bitArch = ^uint(0) >> 63 == 1
const Is32bitArch = ^uint(0) >> 63 == 0
const WordBits = 32 << (^uint(0) >> 63) // 64 or 32
package main
import "fmt"
func main() {
var a [1000]int
// This cost of the two lines is high.
fmt.Println(a) // a is copied
fmt.Printf("Type of a: %T\n", a) // a is copied
// The cost of the two lines is low.
fmt.Printf("%v\n", a[:])
fmt.Println("Type of a:", fmt.Sprintf("%T", &a)[1:])
}
The Go 101 project is hosted on Github. Welcome to improve Go 101 articles by submitting corrections for all kinds of mistakes, such as typos, grammar errors, wording inaccuracies, description flaws, code bugs and broken links.
If you would like to learn some Go details and facts every serveral days, please follow Go 101's official Twitter account @zigo_101.
reflect
standard package.sync
standard package.sync/atomic
standard package.