package main
import "fmt"
type UserID struct {
Name string
Age int
}
type UserProfile struct {
Name string
Tags []string
}
func main() {
a := UserID{"Ann", 30}
b := UserID{"Ann", 30}
fmt.Println(a == b)
x := UserProfile{Name: "Ann", Tags: []string{"go"}}
y := UserProfile{Name: "Ann", Tags: []string{"go"}}
_, _ = x, y
// fmt.Println(x == y) // compile error: struct containing []string cannot be compared
}
package main
import "fmt"
type MyErr struct{}
func (*MyErr) Error() string { return "my error" }
func returnsTypedNil() error {
var e *MyErr = nil
return e
}
func main() {
var p *int = nil
var s []int = nil
var m map[string]int = nil
var err error = returnsTypedNil()
fmt.Println(p == nil)
fmt.Println(len(s), cap(s), s == nil)
fmt.Println(m["missing"])
fmt.Println(err == nil)
}
package main
import "fmt"
type Point struct{ X, Y int } // comparable
type Bag struct{ Items []string } // not comparable because of slice field
func Contains[T comparable](xs []T, target T) bool {
for _, x := range xs {
if x == target {
return true
}
}
return false
}
func main() {
p1, p2 := Point{1, 2}, Point{1, 2}
fmt.Println(p1 == p2)
m := map[Point]string{p1: "value"}
fmt.Println(m[p2])
fmt.Println(Contains([]string{"a", "b"}, "b"))
var a any = []int{1}
var b any = []int{1}
_, _ = a, b
// fmt.Println(a == b) // panic: comparing uncomparable type []int
}
package main
import "fmt"
func main() {
s := "é🙂"
fmt.Println(len(s)) // bytes: é is 2 bytes, 🙂 is 4 bytes
fmt.Println(len([]rune(s))) // Unicode code points
fmt.Printf("first byte: %x\n", s[0])
for i, r := range s {
fmt.Printf("byte index %d: %q U+%04X\n", i, r, r)
}
}
package main
import "fmt"
func main() {
a := [3]int{1, 2, 3}
b := a
b[0] = 99
fmt.Println(a, b)
s := []int{1, 2, 3}
t := s
t[0] = 99
fmt.Println(s, t)
fmt.Println(len(s), cap(s))
}
Goのmapのキーの型は比較可能(comparable)である必要があり、スライス、マップ、関数を直接キーとして使用することはできません。存在しないキーを参照すると要素型のゼロ値が返されるため、存在しないことと格納されているゼロ値を区別するにはcomma-ok構文(`v, ok := m[k]`)を使用します。nilマップからの読み出しやrangeによる反復処理は可能ですが、代入を行うとパニックが発生するため、書き込み前に初期化する必要があります。マップの反復順序は未規定(unspecified)であり、コードがその順序に依存してはなりません。
package main
import "fmt"
func main() {
counts := map[string]int{"a": 0, "b": 2}
fmt.Println(counts["missing"]) // zero value for int
v, ok := counts["a"]
fmt.Println(v, ok) // present even though value is zero
var m map[string]int
fmt.Println(m["x"]) // read from nil map is OK
// m["x"] = 1 // panic: assignment to entry in nil map
m = make(map[string]int)
m["x"] = 1
for k, v := range counts {
fmt.Println(k, v) // order is not guaranteed
}
}
package main
import "fmt"
func main() {
base := []int{1, 2, 3, 4}
a := base[:2] // len 2, cap 4
b := base[2:] // len 2, cap 2
a[0] = 99
fmt.Println(base, a, b)
a = append(a, 77) // reuses base's backing array, overwrites base[2]
fmt.Println(base, a, b)
c := append([]int(nil), base[:2]...) // defensive copy
c[0] = 42
fmt.Println(base, c)
}
package main
func collectNoPrealloc(input []int) []int {
var out []int
for _, v := range input {
out = append(out, v*2)
}
return out
}
func collectPrealloc(input []int) []int {
out := make([]int, 0, len(input))
for _, v := range input {
out = append(out, v*2)
}
return out
}
var in <-chan int = source
for in != nil {
select {
case v, ok := <-in:
if !ok {
in = nil // disables this receive case
continue
}
fmt.Println(v)
case <-ctx.Done():
return
}
}
package main
import (
"sync"
"sync/atomic"
)
var requests atomic.Int64
func recordRequest() {
requests.Add(1) // one independent counter update
}
type Account struct {
mu sync.Mutex
balance int
limit int
}
func (a *Account) Withdraw(n int) bool {
a.mu.Lock()
defer a.mu.Unlock()
// The check and update must be one protected invariant.
if a.balance-n < -a.limit {
return false
}
a.balance -= n
return true
}
package worker
import (
"context"
"sync"
)
type Job int
type Result int
func StartWorkers(ctx context.Context, jobs <-chan Job, n int) <-chan Result {
results := make(chan Result)
var wg sync.WaitGroup
wg.Add(n)
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
for {
select {
case <-ctx.Done():
return
case j, ok := <-jobs:
if !ok {
return
}
r := Result(j * 2)
select {
case results <- r:
case <-ctx.Done():
return
}
}
}
}()
}
go func() {
wg.Wait()
close(results) // close after all senders are done
}()
return results
}