make() never returns nil. It initializes slices, maps, and channels:
s := make([]int, 0) // non-nil empty slice
m := make(map[string]int) // non-nil empty map
c := make(chan int) // non-nil channelYou get nil with the zero value (no make):
var s []int // nil slice
var m map[string]int // nil map
var c chan int // nil channelnil |
make() |
|
|---|---|---|
| Read from map | returns zero value | returns zero value |
| Write to map | panics | works |
Slice append |
works | works |
| Slice len/cap | 0/0 | 0/0 (but non-nil) |
== nil |
true | false |
type Writer interface {
Write(p []byte) (n int, err error)
}
type FileWriter struct{}
func (f FileWriter) Write(p []byte) (int, error) {
return len(p), nil
}
// FileWriter implicitly satisfies Writer
var w Writer = FileWriter{}Go uses embedding instead of inheritance:
type Base struct{}
func (b Base) Greet() string { return "hello" }
type Child struct {
Base
}
func (c Child) Greet() string { return "hi" } // overrides
c := Child{}
c.Greet() // "hi"
c.Base.Greet() // "hello"func Map[T any, U any](s []T, f func(T) U) []U {
result := make([]U, len(s))
for i, v := range s {
result[i] = f(v)
}
return result
}func Min[T constraints.Ordered](a, b T) T {
if a < b { return a }
return b
}import "sort"
sort.Ints([]int{3,1,2})
sort.Strings([]string{"b","a","c"})
sort.Float64s([]float64{3.1, 1.2})
sort.Slice(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
sort.IntsAreSorted([]int{1,2,3}) // trueimport "container/heap"
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] } // min-heap
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x any) { *h = append(*h, x.(int)) }
func (h *IntHeap) Pop() any {
old := *h
n := len(old)
x := old[n-1]
*h = old[:n-1]
return x
}
h := &IntHeap{3, 1, 2}
heap.Init(h)
heap.Push(h, 0)
min := heap.Pop(h) // 0import "container/list"
l := list.New()
l.PushBack(1)
l.PushBack(2)
l.PushFront(0)
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
l.Remove(l.Front())
l.Len() // 2import "container/ring"
r := ring.New(3) // ring of size 3
r.Value = "a"
r = r.Next()
r.Value = "b"
r = r.Next()
r.Value = "c"
r.Do(func(v any) {
fmt.Println(v) // a, b, c
})
r.Move(1) // move forward 1
r.Len() // 3import "slices"
s := []int{3, 1, 2, 1}
slices.Sort(s) // [1,1,2,3]
slices.Contains(s, 2) // true
slices.Index(s, 1) // 0
slices.Compact(s) // [1,2,3] removes consecutive dupes
slices.Reverse(s)
slices.Min(s) // 1
slices.Max(s) // 3
slices.BinarySearch(s, 2)import "maps"
m1 := map[string]int{"a": 1}
m2 := map[string]int{"b": 2}
maps.Copy(m1, m2) // m1 = {"a":1, "b":2}
maps.Equal(m1, m2) // false
maps.DeleteFunc(m1, func(k string, v int) bool {
return v < 2
})import "strings"
strings.Contains("hello", "ell") // true
strings.HasPrefix("hello", "he") // true
strings.HasSuffix("hello", "lo") // true
strings.Split("a,b,c", ",") // ["a","b","c"]
strings.Join([]string{"a","b"}, "-") // "a-b"
strings.Replace("hello", "l", "r", 1) // "herlo"
strings.ReplaceAll("hello", "l", "r") // "herro"
strings.Trim(" hi ", " ") // "hi"
strings.ToLower("HI") // "hi"
strings.ToUpper("hi") // "HI"
strings.Fields("a b c") // ["a","b","c"]var b strings.Builder
b.WriteString("hello")
b.WriteString(" world")
b.String() // "hello world"A rune is an alias for int32 representing a Unicode code point:
var r rune = 'A' // same as int32 = 65import "unicode"
unicode.IsLetter('a') // true
unicode.IsDigit('5') // true
unicode.IsUpper('A') // true
unicode.IsLower('a') // true
unicode.IsSpace(' ') // true
unicode.IsPunct('!') // true
unicode.ToUpper('a') // 'A'
unicode.ToLower('A') // 'a'
unicode.ToTitle('a') // 'A'import "unicode/utf8"
utf8.RuneCountInString("héllo") // 5 (not 6 bytes)
utf8.RuneLen('é') // 2 bytes
utf8.ValidString("hello") // true
utf8.DecodeRuneInString("é") // 'é', 2s := "hello"
runes := []rune(s) // string -> rune slice
str := string(runes) // rune slice -> string
// Iterating runes in a string
for i, r := range "héllo" {
fmt.Println(i, r, string(r))
}