Go
Packaging
- File starts with
package <name>
. - A name is exported if it begins with a capital letter.
go
package main
import (
"fmt"
"math"
)
...
Functions
func
keyword.- Omit shared type in params.
- Multiple return values.
- Named return values.
- Rest params looks like TypeScript.
Declarations
- No colon between name and type.
- May omit shared type.
- Read left to right, compared to C's read in a spiral.
go
var i, j int = 1, 2
x, y := true, 1
var (
u bool = true
v int = 1
)
Types
Basic Types
go
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64
complex64 complex128
uintptr // raw pointer
byte // alias for uint8
rune // alias for int32, represents a Unicode code point
- "Zero value" as default.
- Explicit type conversion:
float64(i)
- Numeric constants are high-precision and can be used as any numeric type.
Pointer Types
go
*T
nil
as default&v
and*p
to ref and deref- Implicit deref for struct member access.
- No pointer arithmetic (like reference?)
Interface Types
go
type any = interface {}
type error interface { Error() string }
It seems that in history
any
was added in 1.18 as an alias ofinterface {}
, that's why it is a newtype instead of an interface declaration.
Composite Types
go
[n]T
[]T
map[K]V
chan T, chan<- T, <-chan T
struct { ... }
func(A1, A2) R
- Array, slice and map are operated by a set of builtin methods:
make
,len
,cap
,append
,delete
, ...
Newtype
go
type MyFloat float64
Control Statements
- No parens, like Rust.
- All loops are
for
:
go
// Conventional for loop
for i := 0; i < 10; i++ {
...
}
// while loop
for sum < 1000 {
...
}
// forever loop
for {
...
}
// Range loop
for i, v := range arr {
...
}
- If (and switch) can have a short statement:
go
if v := math.Pow(x, n); v < lim {
return v
} else {
fmt.Printf("%g >= %g\n", v, lim)
}
- Switch works like JS: case values can be expressions.
Defer
- Not executed until the surrounding function returns.
- Stacked: last in first out.
TODO: https://golang.google.cn/blog/defer-panic-and-recover
Struct
- Constructed by order/name
- Implicit default value for each field
go
type Vertex struct {
X, Y int
}
var (
v1 = Vertex{1, 2}
v2 = Vertex{X: 1} // Y:0 is implicit
)
Methods
- Function with a receiver argument, which may be a pointer.
- Can only declare methods for types defined in the same package.
→ May require a newtype. - Method's responsibility to handle
nil
value.
go
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
Interfaces
- Interfaces are implemented implicitly. (e.g.
any
) - Interface value can be considered as
(value, type)
:
go
type I interface {
Stringer // Interface embedding
Value() int // Method set
~int | ~string // Type set
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
Type Assertions
go
func main() {
var i any = "hello"
s, ok := i.(int)
s := i.(int) // Panic
}
Type Switches
go
func do(i any) {
switch v := i.(type) {
case int: fmt.Println(v * 2)
case string: fmt.Println(len(v))
default: fmt.Printf("%T\n", v)
}
}
It seems that
.(type)
can only be used in a switch.
Type parameters
- Explicit constraint is required.
- No HKT.
go
func Index[T comparable, ](s []T, x T) int {
for i, v := range s {
if v == x {
return i
}
}
return -1
}
type List[T any] struct {
next *List[T]
val T
}
func main() {
var f func(s []int, x int) int
f = Index[int]
}
Goroutine
- Lightweight: Multiple goroutines on OS threads. Go's runtime handles their scheduling.
- Launch anywhere: No function coloring.
- Channel as builtin.
go
func sum(s []int, c chan int) {
sum := ...
c <- sum // send sum to c
}
func main() {
s := []int{...}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}
select
channel
- Race for the ready case.
- May have a default case to make it non-blocking.
go
func main() {
start := time.Now()
tick := time.Tick(100 * time.Millisecond)
boom := time.After(500 * time.Millisecond)
for {
select {
case <-tick:
fmt.Println("tick.")
case <-boom:
fmt.Println("BOOM!")
return
default:
fmt.Println("wait.")
time.Sleep(50 * time.Millisecond)
}
}
}
TODO: How goroutine is implemented.
meow
TODO.