My place to collect information about Go
package main
func main() {
println("Hello, Go!") // Built-in println function
}
- ref/spec#Program_execution
- ref/spec#Bootstrapping
- doc/effective_go#package-names
- tour/basics/1
- pkg/builtin/#println
Go only has 25 keywords!
break, case, chan, const, continue,
default, defer, else, fallthrough, for,
func, go, goto, if, import,
interface, map, package, range, return,
select, struct, switch, type, var
"Syntax is clean and light on keywords"
There is no guarantee that the print and println functions will stay in the language!
append, cap, close, complex, copy,
delete, imag, len, make, new,
panic, print, println, real, recover
string
bool
uint, uint8, uint16, uint32, uint64, uintptr, int, int8, int16, int32, int64
byte // alias for uint8
rune // alias for int32
float32, float64
complex64, complex128
pointer, function, interface, slice, channel, map
array, struct
"" // for strings
false // for booleans
0 // for numeric types
nil // for pointers, functions, interfaces, slices, channels, and maps
// each element of an array of structs will have its fields zeroed if no value is specified
- "Avoid package names like base, common, or util"
- "A package's name should describe its purpose"
- "A variable's name should describe its content"
- "Use the smallest scope possible, declare variable close to their use"
- "Functions should be named for the result they return"
- "Methods should be named for the action they perform"
- "Methods mutate state, functions transform data"
- "The visibility of a name outside a package is determined by whether its first character is upper case"
- "Finally, the convention in Go is to use MixedCaps or mixedCaps rather than underscores to write multiword names"
- doc/effective_go#names
- blog/package-names
- talks/names
- dave.cheney/practical-go
- dave.cheney/avoid-package-names-like-base-util-or-common
- dave.cheney/you-shouldnt-name-your-variables-after-their-types-for-the-same-reason-you-wouldnt-name-your-pets-dog-or-cat
- yt/What's in a name?, Dave Cheney
- wiki/CodeReviewComments#initialisms
package main
const (
STR = "string"
_ = iota // ignore first value
TWO
SIX = iota * TWO
EIGHT
TEN
)
func main() {
println(STR, TWO, SIX, EIGHT, TEN)
}
package main
var (
str1 = "test"
int1 int
)
func main() {
var str2 string
int2 := 2
println(str1, int1, str2, int2)
}
The new built-in function allocates memory. The first argument is a type,
not a value, and the value returned is a pointer to a newly allocated zero
value of that type.
package main
func main() {
p := new(int) // pointer to int
println(p)
println(*p)
}
The make built-in function allocates and initializes an object of type
slice, map, or chan (only). Like new, the first argument is a type, not
a value. Unlike new, make's return type is the same as the type of its
argument, not a pointer to it.
- ref/spec#Making_slices_maps_and_channels
- doc/effective_go#allocation_make
- tour/moretypes/13
- dave.cheney/go-has-both-make-and-new-functions-what-gives
package main
func main() {
s := make([]int, 10) // slice with len(s) == cap(s) == 10
println(s)
println(s[0])
}
- ref/spec#Packages
- tour/basics/1
- doc/effective_go#package-names
- dave.cheney/avoid-package-names-like-base-util-or-common
- pkg#1
- pkg#2
package main
import (
"fmt"
"log"
)
func main() {
fmt.Println("Hello, Go!") // Println function from the fmt package
log.Println("Hello, Go!") // Println function from the log package
}
package main
func init() {
println("init")
}
func main() {
println("main")
}
package main
import _ "fmt"
func main() {
str := "test"
for _, r := range str {
_ = r
}
}
package main
import "fmt"
func main() {
msg := "Hello, Go!"
}
"A language needs only one conditional control flow construct"
package main
func main() {
a := 0
if a > 0 {
println(">")
} else if a < 0 {
println("<")
} else {
println("=")
}
}
"Go has only one looping construct, the for loop"
package main
func main() {
for {
}
s := []int{1, 2, 3, 4, 5}
for n, v := range s {
println(n, v)
}
for i := 0; i <= 9; i++ {
println(i)
}
}
"A switch statement is a shorter way to write a sequence of if - else statements"
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
r := rand.Intn(3)
switch r {
case 0:
fmt.Println(0)
case 1:
fmt.Println(1)
default:
fmt.Println(2)
}
}
- ref/spec#Switch_statements
- doc/effective_go#switch
- tour/flowcontrol/9
- pkg/math/rand#Seed
- pkg/math/rand#Intn
package main
func f() {}
func echo(s string) {
println("echo: " + s)
}
func sum(i, j int) int {
return i + j
}
func swap(i, j int) (int, int) {
return j, i
}
func main() {
f()
println(f)
echo("func")
println(sum(1, 2))
println(swap(1, 0))
}
- ref/spec#Function_types
- doc/effective_go#functions
- doc/faq#Functions_methods
- tour/basics/4
- tour/basics/5
- tour/basics/6
package main
import "fmt"
type rectangle struct {
description string
a, b int
}
func main() {
r := rectangle{"square", 2, 2}
fmt.Println(r)
}
package main
import "fmt"
type rectangle struct {
description string
a, b int
}
func (r rectangle) area() int {
return r.a * r.b
}
func main() {
r := rectangle{"square", 2, 2}
fmt.Println(r.area())
}
- ref/spec#Method_declarations
- ref/spec#Method_expressions
- ref/spec#Method_values
- tour/methods/1
- tour/methods/2
- tour/methods/3
- doc/effective_go#methods
- doc/faq#Functions_methods
- doc/faq#methods_on_basics
- doc/faq#overloading
package main
import (
"testing"
)
func TestArea(t *testing.T) {
tests := []struct {
name string
rect rectangle
want int
}{
{
"empty rectangle",
rectangle{"empty", 0, 1},
0,
},
{
"special rectangle",
rectangle{"square", 2, 2},
4,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.rect.area(); got != tt.want {
t.Errorf("%s: want[%v] != got[%v]", tt.name, tt.want, got)
}
})
}
}
- doc/faq#Packages_Testing
- doc/faq#How_do_I_write_a_unit_test
- doc/faq#testing_framework
- doc/code#Testing
- doc/faq#assertions
- wiki/TableDrivenTests
- wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
- dave.cheney/prefer-table-driven-tests
- dave.cheney/test-fixtures-in-go
"Files whose names begin with _
(including _test.go
) or .
are ignored."
package main
func main() {
println("func main")
f1()
}
func f1() {
defer f2()
println("func f1")
}
func f2() {
println("func f2")
}
package main
import "os"
func main() {
if _, err := os.Open(""); err != nil {
os.Exit(1)
}
}
- ref/spec#Errors
- doc/effective_go#errors
- doc/faq#exceptions
- blog/error-handling-and-go
- blog/errors-are-values
- pkg/os#Open
- pkg/os#Exit
package main
func main() {
defer func() {
if msg, ok := recover().(string); ok {
print("recover: " + msg)
}
}()
panic("panic msg")
}
- doc/effective_go#panic
- doc/effective_go#recover
- blog/defer-panic-and-recover
- ref/spec#Handling_panics
- ref/spec#Run_time_panics
- ref/spec#Type_assertions
- medium/go-how-does-a-program-recover
go mod init
go mod tidy
package main
func main() {
ch := make(chan string)
go func(chan string) {
ch <- "Hello, Go!" // write to channel
}(ch)
println(<-ch) // read from channel
}
- ref/spec#Channel_types
- ref/spec#Making_slices_maps_and_channels
- doc/effective_go#channels)
- doc/effective_go#chan_of_chan
package main
func add[T int | string](s []T) T {
var r T
for _, v := range s {
r += v
}
return r
}
func main() {
i := []int{1, 2, 3}
s := []string{"One", "Two", "Three"}
println(add(i))
println(add(s))
}