├── README.md ├── examples ├── array-copy.go ├── arrays-pass.go ├── arrays.go ├── bool-bits.go ├── bool.go ├── byte-declarations.go ├── constants-compression.go ├── constants-iota-expr.go ├── constants-iota-generator-fun │ ├── combined.go │ ├── main.go │ └── state_string.go ├── constants-iota-types-replaced.go ├── constants-iota-types.go ├── constants-iota.go ├── constants-time-2-behind.go ├── constants-time-2.go ├── constants-time-3.go ├── constants-time-4.go ├── constants-time-5.go ├── constants-time-err.txt ├── constants-time.go ├── empty-struct-array.go ├── empty-struct-nested.go ├── empty-struct-slice.go ├── empty-struct-use.go ├── empty-struct.go ├── float-casting.go ├── floats-math-const-expl.go ├── floats-math-const.go ├── floats-math-vars-expl.go ├── floats-math-vars.go ├── floats-sizes.go ├── int-32bit.txt ├── int-arch-faker.go ├── int-casting.go ├── int-example.go ├── int-sizes.txt ├── int.go ├── interfaces-nils.go ├── interfaces.go ├── ints.go ├── maps-rewrite.txt ├── pointer.go ├── position-struct.go ├── runes-slice.go ├── runes-strings.go ├── runes.go ├── slice-header.txt ├── slices-sizes.go ├── slices.go ├── strings-indexing-awry-explained.go ├── strings-indexing-awry-fixed.go ├── strings-indexing-awry.go ├── strings-indexing-bytes.go ├── strings-indexing.go ├── strings-loop-fixed.go ├── strings-loop.go ├── strings-range-null.go ├── strings-range.go ├── strings-sizes.go ├── strings-slice-comparison-2.go ├── strings-slice-comparison-3.go ├── strings-slice-comparison.go ├── strings-slice-comparison.txt ├── strings.go ├── structs-sizes-complex.go ├── structs-sizes-padding-alt.go ├── structs-sizes-padding-bools-more-awry.go ├── structs-sizes-padding-bools-more.go ├── structs-sizes-padding-bools.go ├── structs-sizes-padding-explained.go ├── structs-sizes-padding.go ├── structs-sizes.go ├── structs.go └── uints.go ├── go.mod ├── go.sum ├── helpers └── size │ └── size.go ├── html └── ints.html ├── presentation.slide └── theme ├── static ├── article.css ├── dir.css ├── dir.js ├── favicon.ico ├── jquery-ui.js ├── notes.css ├── notes.js ├── slides.js └── styles.css └── templates ├── action.tmpl ├── article.tmpl ├── dir.tmpl └── slides.tmpl /README.md: -------------------------------------------------------------------------------- 1 | # All Types of Go Types 2 | 3 | ## GoWest 2020 4 | 5 | Carson Anderson 6 | 7 | DevX Engineer, Weave 8 | 9 | @carson_ops 10 | 11 | ## Runing it Locally 12 | 13 | This presentation uses a custom theme and can be run locally by installing the present tool and starting it: 14 | 15 | ```bash 16 | present -use_playground=false -base theme 17 | ``` 18 | -------------------------------------------------------------------------------- /examples/array-copy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | arr := [3]bool{true, false, true} 7 | arrCopy := arr 8 | 9 | // Now change the copy 10 | arrCopy[1] = true 11 | 12 | fmt.Println("arr", arr) 13 | fmt.Println("arrCopy", arrCopy) 14 | } 15 | -------------------------------------------------------------------------------- /examples/arrays-pass.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var arr [3]bool 7 | changeToTrue(arr) 8 | fmt.Println(arr) 9 | } 10 | 11 | func changeToTrue(arr [3]bool) { 12 | for i := range arr { 13 | arr[i] = true 14 | } 15 | } 16 | 17 | // END OMIT 18 | -------------------------------------------------------------------------------- /examples/arrays.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var bools [50]bool 10 | fmt.Println("size is", unsafe.Sizeof(bools), "bytes") 11 | 12 | fmt.Println("index 0 is:", bools[0]) 13 | 14 | bools[42] = true 15 | fmt.Println("index 42 is:", bools[42]) 16 | } 17 | -------------------------------------------------------------------------------- /examples/bool-bits.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var b bool 10 | fmt.Println(unsafe.Sizeof(b)*8, "bits") 11 | } 12 | 13 | // Partial copy of https://golang.org/src/unsafe/unsafe.go?s=8189:8225#L178 14 | // START OMIT 15 | // Sizeof takes an expression x of any type and returns the size in bytes 16 | // of a hypothetical variable v as if v was declared via var v = x. 17 | // The size does not include any memory possibly referenced by x. 18 | // For instance, if x is a slice, Sizeof returns the size of the slice 19 | // descriptor, not the size of the memory referenced by the slice. 20 | // The return value of Sizeof is a Go constant. 21 | func Sizeof(x ArbitraryType) uintptr { 22 | // END OMIT 23 | return 0 24 | } 25 | 26 | type ArbitraryType string 27 | -------------------------------------------------------------------------------- /examples/bool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var b bool 10 | fmt.Println(unsafe.Sizeof(b)) 11 | } 12 | 13 | // Partial copy of https://golang.org/src/unsafe/unsafe.go?s=8189:8225#L178 14 | // START OMIT 15 | // Sizeof takes an expression x of any type and returns the size in bytes // HL 16 | // of a hypothetical variable v as if v was declared via var v = x. 17 | // The size does not include any memory possibly referenced by x. 18 | // For instance, if x is a slice, Sizeof returns the size of the slice 19 | // descriptor, not the size of the memory referenced by the slice. 20 | // The return value of Sizeof is a Go constant. 21 | func Sizeof(x ArbitraryType) uintptr { 22 | // END OMIT 23 | return 0 24 | } 25 | 26 | type ArbitraryType string 27 | -------------------------------------------------------------------------------- /examples/byte-declarations.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var ( 6 | b1 byte = 0 // integer literal 7 | b2 byte = 0xa // hex notation 8 | b3 byte = 'd' // rune notation 9 | b4 byte = 1_01 // integer literal w/underscore 10 | b5 byte = 0b1100110 // binary notation 11 | ) 12 | 13 | func main() { 14 | // Bytes are an alias to int8, and are printed as one by default 15 | fmt.Println(b1, b2, b3, b4, b5) 16 | } 17 | -------------------------------------------------------------------------------- /examples/constants-compression.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const ( 6 | Created, Starting, Started, Done = iota, iota, iota, iota 7 | ) 8 | 9 | func main() { 10 | fmt.Println(Created, Starting, Started, Done) 11 | } 12 | -------------------------------------------------------------------------------- /examples/constants-iota-expr.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // BEGIN OMIT 6 | const ( 7 | x = iota * 2 // index 0 means iota == 0 8 | y = iota + iota // index 1 means iota == 1 9 | _ // index 2 means iota == 2 10 | z = iota * 1.002 // index 3 means iota == 3 11 | ) 12 | 13 | func main() { 14 | fmt.Println(x, y, z) 15 | } 16 | 17 | // END OMIT 18 | -------------------------------------------------------------------------------- /examples/constants-iota-generator-fun/combined.go: -------------------------------------------------------------------------------- 1 | // This file has been MANUALLY CREATED by merging the code from `main.go` 2 | // and the generated code from `state_string.go` together. 3 | // 4 | // This files has been created for easy use in the play command during present 5 | // THIS IS NOT REQUIRED FOR NORMAL USE 6 | 7 | // This file is in it's own folder because that is a requirement for 8 | // go generate to work. 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | "strconv" 14 | ) 15 | 16 | // BEGIN OMIT 17 | //go:generate stringer -type=State // HL 18 | type State int 19 | 20 | const ( 21 | Created State = iota 22 | Starting 23 | Started 24 | Done 25 | ) 26 | 27 | func main() { 28 | fmt.Println(Created, Starting, Started, Done) 29 | } 30 | 31 | // END OMIT 32 | 33 | // Code generated by "stringer -type=State"; DO NOT EDIT. 34 | 35 | func _() { 36 | // An "invalid array index" compiler error signifies that the constant values have changed. 37 | // Re-run the stringer command to generate them again. 38 | var x [1]struct{} 39 | _ = x[Created-0] 40 | _ = x[Starting-1] 41 | _ = x[Started-2] 42 | _ = x[Done-3] 43 | } 44 | 45 | const _State_name = "CreatedStartingStartedDone" 46 | 47 | var _State_index = [...]uint8{0, 7, 15, 22, 26} 48 | 49 | func (i State) String() string { 50 | if i < 0 || i >= State(len(_State_index)-1) { 51 | return "State(" + strconv.FormatInt(int64(i), 10) + ")" 52 | } 53 | return _State_name[_State_index[i]:_State_index[i+1]] 54 | } 55 | -------------------------------------------------------------------------------- /examples/constants-iota-generator-fun/main.go: -------------------------------------------------------------------------------- 1 | // This file is in it's own folder because that is a requirement for 2 | // go generate to work. 3 | package main 4 | 5 | import "fmt" 6 | 7 | // BEGIN OMIT 8 | //go:generate stringer -type=State // HL 9 | type State int 10 | 11 | const ( 12 | Created State = iota 13 | Starting 14 | Started 15 | Done 16 | ) 17 | 18 | func main() { 19 | fmt.Println(Created, Starting, Started, Done) 20 | } 21 | 22 | // END OMIT 23 | -------------------------------------------------------------------------------- /examples/constants-iota-generator-fun/state_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=State"; DO NOT EDIT. 2 | 3 | package main 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[Created-0] 12 | _ = x[Starting-1] 13 | _ = x[Started-2] 14 | _ = x[Done-3] 15 | } 16 | 17 | const _State_name = "CreatedStartingStartedDone" 18 | 19 | var _State_index = [...]uint8{0, 7, 15, 22, 26} 20 | 21 | func (i State) String() string { 22 | if i < 0 || i >= State(len(_State_index)-1) { 23 | return "State(" + strconv.FormatInt(int64(i), 10) + ")" 24 | } 25 | return _State_name[_State_index[i]:_State_index[i+1]] 26 | } 27 | -------------------------------------------------------------------------------- /examples/constants-iota-types-replaced.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // BEGIN OMIT 6 | const ( 7 | a = 0 // iota 8 | b int64 = 1 // iota 9 | c float64 = 2 // iota 10 | d complex128 = 3 // iota 11 | ) 12 | 13 | func main() { 14 | // Print value and type of all constants 15 | fmt.Printf("%[1]v:%[1]T\n", a) 16 | fmt.Printf("%[1]v:%[1]T\n", b) 17 | fmt.Printf("%[1]v:%[1]T\n", c) 18 | fmt.Printf("%[1]v:%[1]T\n", d) 19 | } 20 | 21 | // END OMIT 22 | -------------------------------------------------------------------------------- /examples/constants-iota-types.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // BEGIN OMIT 6 | const ( 7 | a = iota 8 | b int64 = iota 9 | c float64 = iota 10 | d complex128 = iota 11 | ) 12 | 13 | // END OMIT 14 | 15 | func main() { 16 | // Print value and type of all constants 17 | fmt.Printf("%[1]v:%[1]T\n", a) 18 | fmt.Printf("%[1]v:%[1]T\n", b) 19 | fmt.Printf("%[1]v:%[1]T\n", c) 20 | fmt.Printf("%[1]v:%[1]T\n", d) 21 | } 22 | -------------------------------------------------------------------------------- /examples/constants-iota.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const ( 6 | Created = iota 7 | Starting 8 | Started 9 | Done 10 | ) 11 | 12 | func main() { 13 | fmt.Println(Created, Starting, Started, Done) 14 | } 15 | -------------------------------------------------------------------------------- /examples/constants-time-2-behind.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | // BEGIN OMIT 10 | const sleepSeconds = 2 11 | // END OMIT 12 | 13 | fmt.Print("sleeping for ", sleepSeconds, " seconds...") 14 | // invalid code do demonstrate the idea beind untyped constants OMIT 15 | time.Sleep(time.Second * time.Duration(sleepSeconds)) // HL 16 | fmt.Println("done") 17 | } 18 | -------------------------------------------------------------------------------- /examples/constants-time-2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | // BEGIN OMIT 10 | const sleepSeconds = 2 11 | // END OMIT 12 | 13 | fmt.Print("sleeping for ", sleepSeconds, " seconds...") 14 | time.Sleep(time.Second * sleepSeconds) 15 | fmt.Println("done") 16 | } 17 | -------------------------------------------------------------------------------- /examples/constants-time-3.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | // BEGIN OMIT 12 | sleepSeconds := 2 13 | // END OMIT 14 | 15 | if len(os.Args) > 1 { 16 | sleepSeconds, _ = strconv.Atoi(os.Args[1]) 17 | } 18 | 19 | fmt.Print("sleeping for ", sleepSeconds, " seconds...") 20 | time.Sleep(time.Second * sleepSeconds) 21 | fmt.Println("done") 22 | } 23 | -------------------------------------------------------------------------------- /examples/constants-time-4.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | sleepSeconds := 2 12 | 13 | if len(os.Args) > 1 { 14 | sleepSeconds, _ = strconv.Atoi(os.Args[1]) 15 | } 16 | 17 | fmt.Print("sleeping for ", sleepSeconds, " seconds...") 18 | time.Sleep(time.Second * time.Duration(sleepSeconds)) // HL 19 | fmt.Println("done") 20 | } 21 | -------------------------------------------------------------------------------- /examples/constants-time-5.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | const sleepSeconds time.Duration = 2 10 | 11 | fmt.Print("sleeping for ", sleepSeconds, " seconds...") 12 | time.Sleep(time.Second * sleepSeconds) // HL 13 | fmt.Println("done") 14 | } 15 | -------------------------------------------------------------------------------- /examples/constants-time-err.txt: -------------------------------------------------------------------------------- 1 | ./prog.go:19:28: invalid operation: time.Second * sleepSeconds 2 | (mismatched types time.Duration and int) 3 | -------------------------------------------------------------------------------- /examples/constants-time.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | fmt.Print("sleeping for 2 seconds...") 10 | time.Sleep(time.Second * 2) 11 | fmt.Println("done") 12 | } 13 | -------------------------------------------------------------------------------- /examples/empty-struct-array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var structArray [100]struct{} 10 | fmt.Println(unsafe.Sizeof(structArray)) 11 | } 12 | -------------------------------------------------------------------------------- /examples/empty-struct-nested.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var nestedStruct struct { 10 | a struct{} 11 | b struct{} 12 | } 13 | fmt.Println(unsafe.Sizeof(nestedStruct)) 14 | } 15 | -------------------------------------------------------------------------------- /examples/empty-struct-slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | // use make to create a slice of len 100 10 | structSlice := make([]struct{}, 100) 11 | fmt.Println(unsafe.Sizeof(structSlice)) 12 | } 13 | -------------------------------------------------------------------------------- /examples/empty-struct-use.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | done := make(chan struct{}) 10 | 11 | fmt.Print("Sleeping...") 12 | go func() { 13 | time.Sleep(time.Second) 14 | done <- struct{}{} 15 | }() 16 | 17 | <-done 18 | fmt.Println("done") 19 | } 20 | -------------------------------------------------------------------------------- /examples/empty-struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var empty struct{} 10 | fmt.Println(unsafe.Sizeof(empty)) 11 | } 12 | -------------------------------------------------------------------------------- /examples/float-casting.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var f32 float32 = 1.002 7 | var f64 float64 = 1.002 8 | 9 | fmt.Println(f64 == float64(f32)) 10 | fmt.Println(f32 == float32(f64)) 11 | } 12 | -------------------------------------------------------------------------------- /examples/floats-math-const-expl.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | const ( 7 | a = 0.1 8 | b = 0.2 9 | c = 0.3 10 | ) 11 | 12 | fmt.Printf("a: %.20f\n", a) 13 | fmt.Printf("b: %.20f\n", b) 14 | fmt.Printf("a+b: %.20f\n", a+b) 15 | fmt.Printf("c: %.20f\n", c) 16 | } 17 | -------------------------------------------------------------------------------- /examples/floats-math-const.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | const ( 7 | a = 0.1 8 | b = 0.2 9 | c = 0.3 10 | ) 11 | fmt.Println(a+b == c) 12 | } 13 | -------------------------------------------------------------------------------- /examples/floats-math-vars-expl.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var ( 7 | a = 0.1 8 | b = 0.2 9 | c = 0.3 10 | ) 11 | 12 | fmt.Printf("a: %.20f\n", a) 13 | fmt.Printf("b: %.20f\n", b) 14 | fmt.Printf("a+b: %.20f\n", a+b) 15 | fmt.Printf("c: %.20f\n", c) 16 | } 17 | -------------------------------------------------------------------------------- /examples/floats-math-vars.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var ( 7 | a = 0.1 8 | b = 0.2 9 | c = 0.3 10 | ) 11 | fmt.Println(a+b == c) 12 | } 13 | -------------------------------------------------------------------------------- /examples/floats-sizes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var f32 float32 = 1.002 10 | fmt.Println(unsafe.Sizeof(f32)*8, "bits") 11 | 12 | var f64 float64 = 1.002 13 | fmt.Println(unsafe.Sizeof(f64)*8, "bits") 14 | } 15 | -------------------------------------------------------------------------------- /examples/int-32bit.txt: -------------------------------------------------------------------------------- 1 | $ GOARCH=386 go run examples/int.go 2 | 32 bits 3 | 32 bits 4 | -------------------------------------------------------------------------------- /examples/int-arch-faker.go: -------------------------------------------------------------------------------- 1 | // This file fakes the output of 2 | // GOARCH=386 go run examples/int.go 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | // BEGIN OMIT 11 | // command: GOARCH=386 go run examples/int.go 12 | // END OMIT 13 | 14 | func main() { 15 | fmt.Println("32 bits") 16 | fmt.Println("32 bits") 17 | } 18 | -------------------------------------------------------------------------------- /examples/int-casting.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var i32 int32 = 1002 7 | var i64 int64 = 1002 8 | 9 | fmt.Println(i64 == int64(i32)) 10 | fmt.Println(i32 == int32(i64)) 11 | } 12 | -------------------------------------------------------------------------------- /examples/int-example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var i int = 10 7 | var i64 int64 = 10 8 | 9 | fmt.Println(i) 10 | fmt.Println(i64) 11 | } 12 | -------------------------------------------------------------------------------- /examples/int-sizes.txt: -------------------------------------------------------------------------------- 1 | uint either 32 or 64 bits // HL 2 | int same size as uint // HL 3 | uintptr an unsigned integer large enough to store the 4 | uninterpreted bits of a pointer value 5 | -------------------------------------------------------------------------------- /examples/int.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var i int 10 | fmt.Println(unsafe.Sizeof(i)*8, "bits") 11 | 12 | var u uint 13 | fmt.Println(unsafe.Sizeof(u)*8, "bits") 14 | } 15 | -------------------------------------------------------------------------------- /examples/interfaces-nils.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | var x *int 9 | var y interface{} 10 | 11 | fmt.Println("x == nil:", x == nil) 12 | fmt.Println("y == nil:", x == nil) 13 | fmt.Println("x == y: ", x == y) 14 | } 15 | -------------------------------------------------------------------------------- /examples/interfaces.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "unsafe" 7 | ) 8 | 9 | // BEGIN OMIT 10 | func printSize(msg string, i interface{}) { 11 | fmt.Printf("\nsizes in bytes for %s '%v':\n", msg, i) 12 | fmt.Println("interface: ", unsafe.Sizeof(i)) 13 | fmt.Println("type: ", reflect.TypeOf(i).Size()) 14 | } 15 | 16 | func main() { 17 | printSize("bool", true) 18 | printSize("untyped const", 1) 19 | printSize("int32 cast const", int32(1)) 20 | printSize("int64 cast const", int64(1)) 21 | printSize("string", "xxxx") 22 | } 23 | 24 | // END OMIT 25 | -------------------------------------------------------------------------------- /examples/ints.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var i8 int8 10 | fmt.Println(unsafe.Sizeof(i8)*8, "bits") 11 | 12 | var i16 int16 13 | fmt.Println(unsafe.Sizeof(i16)*8, "bits") 14 | 15 | var i32 int32 16 | fmt.Println(unsafe.Sizeof(i32)*8, "bits") 17 | 18 | var i64 int64 19 | fmt.Println(unsafe.Sizeof(i64)*8, "bits") 20 | } 21 | -------------------------------------------------------------------------------- /examples/maps-rewrite.txt: -------------------------------------------------------------------------------- 1 | v := m["key"] → runtime.mapaccess1(m, ”key", &v) 2 | v, ok := m["key"] → runtime.mapaccess2(m, ”key”, &v, &ok) 3 | m["key"] = 9001 → runtime.mapinsert(m, ”key", 9001) 4 | delete(m, "key") → runtime.mapdelete(m, “key”) 5 | -------------------------------------------------------------------------------- /examples/pointer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var b bool 10 | fmt.Println("bool size:", unsafe.Sizeof(b)) 11 | fmt.Println("bool pointer size:", unsafe.Sizeof(&b)) 12 | 13 | var i64 int64 14 | fmt.Println("int64 size:", unsafe.Sizeof(i64)) 15 | fmt.Println("int64 pointer size:", unsafe.Sizeof(&i64)) 16 | 17 | s := []bool{} 18 | fmt.Println("slice size:", unsafe.Sizeof(s)) 19 | fmt.Println("slice pointer size:", unsafe.Sizeof(&s)) 20 | } 21 | -------------------------------------------------------------------------------- /examples/position-struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | type position struct { 9 | x, y int8 10 | } 11 | 12 | func main() { 13 | fmt.Println("position struct sizes") 14 | 15 | // empty vector struct is two bytes 16 | var p position 17 | fmt.Println("single: ", unsafe.Sizeof(p)) 18 | 19 | // array of positions is len * 2 bytes, or 200 bytes 20 | var positionArray [100]position 21 | fmt.Println("len 100 array: ", unsafe.Sizeof(positionArray)) 22 | 23 | // slize of position slice is always slice header length 24 | // note that the underlying array for this slice still exists 25 | // and still uses 200 bytes for a capacity of 100 26 | positionSlice := make([]position, 100) 27 | fmt.Println("len 100 slice: ", unsafe.Sizeof(positionSlice)) 28 | } 29 | -------------------------------------------------------------------------------- /examples/runes-slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var ( 7 | x = 'x' 8 | y = '😊' 9 | ni = '日' 10 | ) 11 | 12 | fmt.Print( 13 | []byte(string(x)), "\n", 14 | []byte(string(y)), "\n", 15 | []byte(string(ni)), "\n", 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /examples/runes-strings.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var ( 7 | x = 'x' 8 | y = '😊' 9 | ni = '日' 10 | ) 11 | 12 | fmt.Println( 13 | string(x), 14 | string(y), 15 | string(ni), 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /examples/runes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var ( 7 | x = 'x' 8 | y = '😊' 9 | ni = '日' 10 | ) 11 | 12 | fmt.Println(x, y, ni) 13 | } 14 | -------------------------------------------------------------------------------- /examples/slice-header.txt: -------------------------------------------------------------------------------- 1 | type sliceHeader struct { 2 | ptr *[]Elem // 8 bytes for amd64 3 | len int // 8 bytes for amd64 4 | cap int // 8 bytes for amd64 5 | } 6 | -------------------------------------------------------------------------------- /examples/slices-sizes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | s1 := []bool{} 10 | fmt.Println("header bytes: ", unsafe.Sizeof(s1)) 11 | fmt.Println( 12 | "array bytes: ", cap(s1), 13 | ) 14 | 15 | fmt.Println() 16 | 17 | s2 := make([]bool, 100) 18 | fmt.Println("header bytes: ", unsafe.Sizeof(s2)) 19 | fmt.Println( 20 | "array bytes: ", cap(s2), 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /examples/slices.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // bools := []bool{true, true, false, false} 7 | // printBools(bools) 8 | 9 | // rangeSlices() 10 | 11 | sliceCopies() 12 | 13 | // stringSliceConversion() 14 | } 15 | 16 | // Go Passes everything by copy. How many values are copied 17 | // when we run this function? 18 | // one value - A slice pointer 19 | // three values - All list elements 20 | // four values - All list elements 21 | func printBools(bools []bool) { 22 | for i, b := range bools { 23 | fmt.Println("index", i, "is", b) 24 | } 25 | } 26 | 27 | // why can you range over a nil slice? 28 | func rangeSlices() { 29 | // Yep! 30 | var bools []bool 31 | for _, b := range bools { 32 | fmt.Println(b) 33 | } 34 | 35 | // And you can append to one too! 36 | // very handy with maps of slices 37 | bools = append(bools, true) 38 | } 39 | 40 | // Do slice copies cause allocations? 41 | func sliceCopies() { 42 | slice := []byte{0x1, 0x2, 0x3} 43 | fmt.Println(slice[0], &slice[0]) 44 | 45 | newSlice := slice 46 | fmt.Println(newSlice[0], &newSlice[0]) 47 | 48 | // modify a member 49 | slice[0] = 0x4 50 | fmt.Println(slice[0], &slice[0]) 51 | fmt.Println(newSlice[0], &newSlice[0]) 52 | } 53 | 54 | // Do slice conversions caus allocations? 55 | // i.e. is new data created when you `s := string(slice)`? 56 | func stringSliceConversion() { 57 | slice := []byte{0x1, 0x2, 0x3} 58 | fmt.Println(&slice[0]) 59 | 60 | str := string(slice) 61 | 62 | newSlice := []byte(str) 63 | fmt.Println(&newSlice[0]) 64 | 65 | // modify a member 66 | slice[0] = 0x4 67 | fmt.Println(slice[0], &slice[0]) 68 | fmt.Println(newSlice[0], &newSlice[0]) 69 | } 70 | -------------------------------------------------------------------------------- /examples/strings-indexing-awry-explained.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | s := "I am a string" 9 | fmt.Println([]byte(s)) 10 | x := s[3] 11 | fmt.Println("at index 3: ", x) 12 | 13 | fmt.Println() 14 | 15 | s = "I ám a string" 16 | fmt.Println([]byte(s)) 17 | x = s[3] 18 | fmt.Println("at index 3: ", x) 19 | } 20 | -------------------------------------------------------------------------------- /examples/strings-indexing-awry-fixed.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func main() { 9 | // by explicitly converting to a rune slice 10 | // you can get indexes in a more natural way 11 | // NOTE: This is still not 100% reliable! 12 | s := "I ám a string" 13 | x := []rune(s)[3] // HL 14 | fmt.Println("at index 3: ", x) 15 | fmt.Println("type is: ", reflect.TypeOf(x)) 16 | fmt.Println("as string: ", string(x)) 17 | } 18 | -------------------------------------------------------------------------------- /examples/strings-indexing-awry.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func main() { 9 | // strings with non-ascii bytes will mess up indexing 10 | s := "I ám a string" 11 | x := s[3] 12 | fmt.Println("at index 3: ", x) 13 | fmt.Println("type is: ", reflect.TypeOf(x)) 14 | fmt.Println("as string: ", string(x)) 15 | } 16 | -------------------------------------------------------------------------------- /examples/strings-indexing-bytes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func main() { 9 | buf := []byte("I á") 10 | buf = append(buf, 0x00) // write nul byte 11 | buf = append(buf, 'm') // write ascii 'a' byte 12 | s := string(buf) + " a string" 13 | 14 | // prints like normal 15 | fmt.Printf("s is : '%s'\n", s) 16 | 17 | // even a []rune index is still off 18 | x := []rune(s)[3] 19 | fmt.Println("at index 3: ", x) 20 | fmt.Println("type is: ", reflect.TypeOf(x)) 21 | fmt.Println("as string: '", string(x), "'") 22 | } 23 | -------------------------------------------------------------------------------- /examples/strings-indexing.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func main() { 9 | // ascii only strings can be safely indexed as normal 10 | s := "I am a string" 11 | x := s[3] 12 | fmt.Println("at index 3: ", x) 13 | fmt.Println("type is: ", reflect.TypeOf(x)) 14 | fmt.Println("as string: ", string(x)) 15 | } 16 | -------------------------------------------------------------------------------- /examples/strings-loop-fixed.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | const s = `西に行く` 7 | 8 | runes := []rune(s) 9 | for i := 0; i < len(runes); i++ { 10 | fmt.Println( 11 | runes[i], ":", string(runes[i]), 12 | ) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/strings-loop.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | const s = `西に行く` 7 | 8 | for i := 0; i < len(s); i++ { 9 | fmt.Println( 10 | s[i], ":", string(s[i]), 11 | ) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/strings-range-null.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | raw := []byte(string(`西に`)) 7 | raw = append(raw, 0b0) // add NULL byte in the middle 8 | raw = append(raw, []byte(string(`行く`))...) 9 | 10 | s := string(raw) 11 | 12 | for _, x := range s { 13 | fmt.Println( 14 | x, ":", string(x), 15 | ) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/strings-range.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | const s = `西に行く` 7 | 8 | for _, x := range s { 9 | fmt.Println( 10 | x, ":", string(x), 11 | ) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/strings-sizes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | s := "I am a string" 10 | fmt.Println("string size: ", unsafe.Sizeof(s)) 11 | 12 | s = "I am a longer string" 13 | fmt.Println("longer string size: ", unsafe.Sizeof(s)) 14 | } 15 | -------------------------------------------------------------------------------- /examples/strings-slice-comparison-2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("string sizes: ") 10 | var str string = "Hi" 11 | fmt.Println("header: ", unsafe.Sizeof(str)) 12 | fmt.Println("len: ", len(str)) 13 | fmt.Println("total: ", int(unsafe.Sizeof(str))+len(str)) 14 | 15 | fmt.Println() 16 | 17 | fmt.Println("byte slice sizes: ") 18 | slice := []byte(str) 19 | fmt.Println("header: ", unsafe.Sizeof(slice)) 20 | fmt.Println("cap: ", cap(slice)) // you have to use cap for slices 21 | fmt.Println("total: ", int(unsafe.Sizeof(slice))+cap(slice)) 22 | } 23 | -------------------------------------------------------------------------------- /examples/strings-slice-comparison-3.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | str := "Hi" 9 | 10 | slice := []byte(str) 11 | 12 | slice[1] = 'm' 13 | slice = append(slice, 109, 109, 109, 240, 159, 164, 148) 14 | 15 | // print proof 16 | fmt.Println(str) 17 | fmt.Println(string(slice)) 18 | } 19 | -------------------------------------------------------------------------------- /examples/strings-slice-comparison.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var str string = "Hi" 10 | fmt.Println("string bytes: ", unsafe.Sizeof(str)) 11 | 12 | slice := []byte(str) 13 | fmt.Println("slice bytes: ", unsafe.Sizeof(slice)) 14 | } 15 | -------------------------------------------------------------------------------- /examples/strings-slice-comparison.txt: -------------------------------------------------------------------------------- 1 | type stringHeader struct { 2 | ptr *[]Elem // 8 bytes for amd64 3 | len int // 8 bytes for amd64 4 | } 5 | 6 | type sliceHeader struct { 7 | ptr *[]Elem // 8 bytes for amd64 8 | len int // 8 bytes for amd64 9 | cap int // 8 bytes for amd64 10 | } 11 | -------------------------------------------------------------------------------- /examples/strings.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const goWestEN = `GoWest` 6 | const goWestJP = `西に行く` 7 | 8 | func main() { 9 | fmt.Println("-- ASCII --") 10 | examineString(goWestEN) 11 | 12 | fmt.Println("-- Non-ASCII --") 13 | examineString(goWestJP) 14 | } 15 | 16 | func examineString(s string) { 17 | fmt.Println("Whole string: ", s) 18 | 19 | fmt.Println("Index 0: ", s[0]) 20 | 21 | fmt.Println("for loop:") 22 | for i := 0; i < len(s); i++ { 23 | b := s[i] 24 | // the default Println behavor is to print the type (byte) 25 | fmt.Println("rune: ", b) 26 | 27 | // we have to cast to string to get our character 28 | fmt.Printf("quote: %s\n", string(b)) 29 | } 30 | 31 | fmt.Println("for range loop:") 32 | for _, r := range s { 33 | // the default Println behavor is to print the type (byte slice) 34 | fmt.Println("rune: ", r) 35 | 36 | // we have to cast to string to get our character 37 | fmt.Printf("quote: %s\n", string(r)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/structs-sizes-complex.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var data struct { 10 | child struct { 11 | a uint64 // 8 bytes 12 | b uint64 // 8 bytes 13 | } 14 | x uint64 // 8 bytes 15 | y uint64 // 8 bytes 16 | } 17 | 18 | fmt.Println( 19 | unsafe.Sizeof(data.child.a), 20 | "+", 21 | unsafe.Sizeof(data.child.b), 22 | "+", 23 | unsafe.Sizeof(data.x), 24 | "+", 25 | unsafe.Sizeof(data.y), 26 | "=", 27 | unsafe.Sizeof(data), 28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /examples/structs-sizes-padding-alt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var data struct { 10 | x uint32 // 4 bytes 11 | y uint32 // 4 bytes 12 | } 13 | fmt.Println( 14 | unsafe.Sizeof(data.x), 15 | "+", 16 | unsafe.Sizeof(data.y), 17 | "=", 18 | unsafe.Sizeof(data), 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /examples/structs-sizes-padding-bools-more-awry.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var data struct { 10 | x1 bool // 1 bytes 11 | // [7]byte 12 | y uint64 // 8 bytes 13 | x2 bool // 1 bytes 14 | // [7]byte 15 | } 16 | fmt.Println( 17 | unsafe.Sizeof(data.x1), 18 | "+", 19 | unsafe.Sizeof(data.x2), 20 | "+", 21 | unsafe.Sizeof(data.y), 22 | "=", 23 | unsafe.Sizeof(data), 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /examples/structs-sizes-padding-bools-more.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var data struct { 10 | x1 bool // 1 bytes 11 | x2 bool // 1 bytes 12 | // [6]byte 13 | y uint64 // 8 bytes 14 | } 15 | fmt.Println( 16 | unsafe.Sizeof(data.x1), 17 | "+", 18 | unsafe.Sizeof(data.x2), 19 | "+", 20 | unsafe.Sizeof(data.y), 21 | "=", 22 | unsafe.Sizeof(data), 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /examples/structs-sizes-padding-bools.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var data struct { 10 | x bool // 1 bytes 11 | // [7]byte 12 | y uint64 // 8 bytes 13 | } 14 | fmt.Println( 15 | unsafe.Sizeof(data.x), 16 | "+", 17 | unsafe.Sizeof(data.y), 18 | "=", 19 | unsafe.Sizeof(data), 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /examples/structs-sizes-padding-explained.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | var data struct { 5 | x uint32 // 4 bytes 6 | _ [4]byte 7 | y uint64 // 8 bytes 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/structs-sizes-padding.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var data struct { 10 | x uint32 // 4 bytes // HL 11 | y uint64 // 8 bytes 12 | } 13 | fmt.Println( 14 | unsafe.Sizeof(data.x), 15 | "+", 16 | unsafe.Sizeof(data.y), 17 | "=", 18 | unsafe.Sizeof(data), 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /examples/structs-sizes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var data struct { 10 | x uint64 // 8 bytes 11 | y uint64 // 8 bytes 12 | } 13 | 14 | fmt.Println( 15 | unsafe.Sizeof(data.x), 16 | "+", 17 | unsafe.Sizeof(data.y), 18 | "=", 19 | unsafe.Sizeof(data), 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /examples/structs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // BEGIN OMIT 6 | type nothin struct{} 7 | 8 | type data struct { 9 | x int 10 | y int64 11 | } 12 | 13 | func main() { 14 | fmt.Println(nothin{}) 15 | fmt.Println(data{1, 2}) 16 | } 17 | 18 | // END OMIT 19 | -------------------------------------------------------------------------------- /examples/uints.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | var ui8 uint8 10 | fmt.Println(unsafe.Sizeof(ui8)*8, "bits") 11 | 12 | var ui16 uint16 13 | fmt.Println(unsafe.Sizeof(ui16)*8, "bits") 14 | 15 | var ui32 uint32 16 | fmt.Println(unsafe.Sizeof(ui32)*8, "bits") 17 | 18 | var ui64 uint64 19 | fmt.Println(unsafe.Sizeof(ui64)*8, "bits") 20 | } 21 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/carsonoid/gowest2020-go-types 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/davelaursen/present-plus v0.0.0-20150924164712-83b3dc77501f // indirect 7 | github.com/yuin/goldmark v1.4.0 // indirect 8 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect 9 | golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect 10 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect 11 | golang.org/x/tools v0.1.5 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davelaursen/present-plus v0.0.0-20150924164712-83b3dc77501f h1:k8Vxh3NlskkR25ewGbCS/ydL18BxYlVFQtfbLuMHx0I= 2 | github.com/davelaursen/present-plus v0.0.0-20150924164712-83b3dc77501f/go.mod h1:fhPWdeZWNxQXWh1odOF0/qlR5B3BdIxQ4OmIv67M838= 3 | github.com/yuin/goldmark v1.1.32 h1:5tjfNdR2ki3yYQ842+eX2sQHeiwpKJ0RnHO4IYOc4V8= 4 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 5 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 6 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 7 | github.com/yuin/goldmark v1.4.0 h1:OtISOGfH6sOWa1/qXqqAiOIAO6Z5J3AEAE18WAq6BiQ= 8 | github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 9 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 10 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 11 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 12 | golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= 13 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 14 | golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= 15 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 16 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 17 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 18 | golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= 19 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 20 | golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4= 21 | golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 22 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 23 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 24 | golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= 25 | golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 26 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 27 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 28 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 29 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 30 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 31 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 32 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 33 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 34 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 35 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 36 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 37 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= 38 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 39 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 40 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 41 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 42 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 43 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 44 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 45 | golang.org/x/tools v0.0.0-20200815165600-90abf76919f3 h1:0aScV/0rLmANzEYIhjCOi2pTvDyhZNduBUMD2q3iqs4= 46 | golang.org/x/tools v0.0.0-20200815165600-90abf76919f3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 47 | golang.org/x/tools v0.0.0-20200904185747-39188db58858 h1:xLt+iB5ksWcZVxqc+g9K41ZHy+6MKWfXCDsjSThnsPA= 48 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= 49 | golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= 50 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 51 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 52 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 53 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 54 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 55 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 56 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 57 | -------------------------------------------------------------------------------- /helpers/size/size.go: -------------------------------------------------------------------------------- 1 | package size 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func InBits(i interface{}) { 9 | // use reflect to get size in bytes 10 | s := reflect.TypeOf(i).Size() 11 | 12 | // print bytes * 8 to get bits 13 | fmt.Println(s * 8) 14 | } 15 | -------------------------------------------------------------------------------- /html/ints.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
TypesSize# Occurences
int? bits52,626
int88 bits2,578
int1616 bits1,855
int3232 bits10,899
int6464 bits15,419
33 | -------------------------------------------------------------------------------- /presentation.slide: -------------------------------------------------------------------------------- 1 | # All Types of Go Types 2 | 3 | Carson Anderson 4 | DevX Engineer, Weave 5 | @carson_ops 6 | 7 | https://github.com/carsonoid/talk-gowest2020-go-types 8 | 9 | ## Questions I Had About Go Types 10 | 11 | * How big is a bool? 12 | * How big is an `int`? 13 | * What type is a `constant`?s 14 | * What is `iota`? 15 | * How big is an empty `struct`? 16 | * Are all `nil`s identical? 17 | * Should I pass large `strings`? 18 | * What's a `rune`? 19 | * What happens when I pass a `slice`? 20 | : * When should I pass a `struct` vs `pointer`? 21 | 22 | ## Bools 23 | 24 | ## Q: How big is a bool? 25 | 26 | : We are starting simple, but this shows that even seemingly easy assumptions can be wrong 27 | 28 | A seemingly simple question 29 | 30 | .play examples/bool.go /^func main/,/^} 31 | 32 | : Size is not what is expected 33 | 34 | ## Makes sense... Except! 35 | 36 | : Explain reflect.SizeOf since we will use it a lot 37 | 38 | From the Go docs on `unsafe.SizeOf`: 39 | 40 | .code examples/bool.go /START OMIT/,/END OMIT/ 41 | 42 | > size in bytes 43 | 44 | : Size is not what is expected 45 | 46 | So really... 47 | 48 | .play examples/bool-bits.go /^func main/,/^} 49 | 50 | ## Interesting Golang Type Discoveries 51 | 52 | 1. `bool` can be **more than one bit** 53 | 54 | ## Q: Int Or IntXX? 55 | 56 | What are are these sized `int` types and when should I use them? 57 | 58 | .play examples/int-example.go /^func main/,/^} 59 | 60 | ## IntXX Types Occurances 61 | 62 | How often the different integer types occur in the go source: 63 | 64 | : count from source using 'git ls-files | xargs -n1 grep -Iswo int | wc -l' 65 | : it's a rought calculation, but good enough to illustrate the point 66 | : call out that the int type is used far more than any other type 67 | 68 | .html /html/ints.html 69 | 70 | Plain old `int` is the most used integer type by far. But.. how *big* is it? 71 | 72 | ## intXX Size Proof 73 | 74 | .play examples/ints.go /^func main/,/^} 75 | 76 | ## uintXX Size Proof 77 | 78 | .play examples/uints.go /^func main/,/^} 79 | 80 | ## But what about plain old `int` and `uint`? 81 | 82 | .play examples/int.go /^func main/,/^} 83 | 84 | ## That answers it, right? 85 | 86 | .image https://media.giphy.com/media/SVgKToBLI6S6DUye1Y/giphy.gif _ 800 87 | 88 | ## Try targeting a different architecure with GOARCH 89 | 90 | .code examples/int.go /^func main/,/^} 91 | 92 | .play examples/int-arch-faker.go /BEGIN OMIT/,/END OMIT/ 93 | 94 | 95 | ## int and uint size in Go is implementation-specific 96 | 97 | .link https://golang.org/ref/spec#Numeric_types 98 | 99 | .code examples/int-sizes.txt 100 | 101 | In short: 102 | 103 | * 32 bit for 32 bit systems 104 | * 64 bit for 64 bit systems 105 | 106 | So.. Which one do I use? 107 | 108 | * `(u)int` is suggested for most cases 109 | * `(u)intXX` for shared data models 110 | 111 | ## Interesting Golang Type Discoveries 112 | 113 | 1. `bool` can be **more than one bit** 114 | 1. `int` and `uint` can **change size** 115 | 116 | ## Float Types 117 | 118 | ## Let's compare some floats! 119 | 120 | .play examples/floats-math-vars.go /^func main/,/^} 121 | 122 | ## As expected: float variables have arbitrary precision 123 | 124 | .play examples/floats-math-vars-expl.go /^func main/,/^} 125 | 126 | ## What about float constants? 127 | 128 | .play examples/floats-math-const.go /^func main/,/^} 129 | 130 | ## But how? 131 | 132 | .link https://golang.org/ref/spec#Constants 133 | 134 | > Implementation restriction: Although numeric constants have arbitrary precision in the language, a compiler may implement them using an internal representation with limited precision 135 | 136 | .play examples/floats-math-const-expl.go /^func main/,/^} 137 | 138 | ## Interesting Golang Type Discoveries 139 | 140 | 1. `bool` can be **more than one bit** 141 | 1. `int` and `uint` can **change size** 142 | 1. `floatXX` constants can have **fixed precision** 143 | 144 | ## Constants 145 | 146 | ## Constants - Not what you think 147 | 148 | .play examples/constants-time.go /^func main/,/^} 149 | 150 | ## Lets make that better! 151 | 152 | .play examples/constants-time-2.go /^func main/,/^} 153 | 154 | ## Now make it configurable! 155 | 156 | .play examples/constants-time-3.go /^func main/,/^} 157 | 158 | ## What?? 159 | 160 | .code examples/constants-time-err.txt 161 | 162 | But we only changed one line: 163 | 164 | .code examples/constants-time-2.go /BEGIN OMIT/,/END OMIT/ 165 | .code examples/constants-time-3.go /BEGIN OMIT/,/END OMIT/ 166 | 167 | ## What Type of Constant is that? None! 168 | 169 | .link https://golang.org/ref/spec#Constants 170 | 171 | > Constants may be typed or untyped. Literal constants, true, false, iota, and certain constant expressions containing only untyped constant operands are untyped. 172 | 173 | > A constant may be given a type explicitly by a constant declaration or conversion, or implicitly when used in a variable declaration or an assignment or as an operand in an expression. 174 | 175 | ## Under the hood... 176 | 177 | Go effectively does this for us during compilation 178 | 179 | .code examples/constants-time-2-behind.go /^func main/,/^} 180 | 181 | ## Lets do that then! 182 | 183 | .play examples/constants-time-4.go /^func main/,/^} 184 | 185 | Fun fact: There are still 3 untyped constants in this code! 186 | 187 | ## Interesting Golang Type Discoveries 188 | 189 | 1. `bool` can be **more than one bit** 190 | 1. `int` and `uint` can **change size** 191 | 1. `floatXX` constants can have **fixed precision** 192 | 1. Constants can be **untyped** 193 | 194 | ## iota 195 | 196 | ## What about it? 197 | 198 | Is it a `iota` a type? 199 | 200 | .play examples/constants-iota.go /^const/,/^} 201 | 202 | ## What does the spec say? 203 | 204 | .link https://golang.org/ref/spec#Constants 205 | 206 | > The predeclared identifier iota denotes an integer constant. 207 | 208 | ## But what about this? 209 | 210 | .play examples/constants-iota-types.go /^const/,/^} 211 | 212 | ## Digging deeper... 213 | 214 | .link https://golang.org/ref/spec#Iota 215 | 216 | > Within a constant declaration, the predeclared identifier iota represents **successive untyped integer constants**. 217 | 218 | .play examples/constants-iota-types-replaced.go /BEGIN OMIT/,/END OMIT/ 219 | 220 | ## But that's not all! 221 | 222 | Because `iota` is not a type, but a **dynamic constant**, it a can be treated like a value and even be put into expressions. 223 | 224 | .play examples/constants-iota-expr.go /^const/,/^} 225 | 226 | It can be thought of as a simple compiler replacement symbol. 227 | 228 | ## Interesting Golang Type Discoveries 229 | 230 | 1. `bool` can be **more than one bit** 231 | 1. `int` and `uint` can **change size** 232 | 1. `floatXX` constants can have **fixed precision** 233 | 1. Constants can be **untyped** 234 | 1. `iota` is an `untyped int` and it **changes value** 235 | 236 | ## One last iota trick 237 | 238 | Use the `stringer` generator for meaningful names! 239 | 240 | .play examples/constants-iota-generator-fun/combined.go /BEGIN OMIT/,/END OMIT/ 241 | 242 | > **Run `go generate` first!!** 243 | 244 | ## Arrays And Slices 245 | 246 | ## Arrays 247 | 248 | Arrays are swaths of contiguous memory for a specific type. 249 | 250 | They have a fixed length and can be indexed to get the value at any point in the array. 251 | 252 | .play examples/arrays.go /^func main/,/^} 253 | 254 | : ## Can you pass an Array? 255 | 256 | : .play examples/arrays-pass.go /^func main/,/END OMIT/ 257 | 258 | ## Array Size? 259 | 260 | So when I pass an array, how much data do I pass? All of it! 261 | 262 | .play -edit examples/array-copy.go /^func main/,/^}/ 263 | 264 | ## Slices 265 | 266 | Slices are a convenience layer on top of arrays, but they are backed by arrays. 267 | 268 | Slices really have **two sizes**, the size of the `sliceHeader` and the size of the underlying `array` 269 | 270 | When you pass a slice around, you pass a copy of the `sliceHeader` which is essentially a 3 word lenght struct that is completely hidden by the language. 271 | 272 | Each slice header can be thought of like a struct with the following composition: 273 | 274 | .code examples/slice-header.txt 275 | 276 | ## Slice Sizes 277 | 278 | So when I pass a slice, how much data am I passing? 279 | 280 | .play examples/slices-sizes.go /^func main/,/^} 281 | 282 | ## Interesting Golang Type Discoveries 283 | 284 | 1. `bool` can be **more than one bit** 285 | 1. `int` and `uint` can **change size** 286 | 1. `floatXX` constants can have **fixed precision** 287 | 1. Constants can be **untyped** 288 | 1. `iota` is an `untyped int` and it **changes value** 289 | 1. All `slice` variables **cost the same** to shallow copy 290 | 291 | ## Bytes 292 | 293 | ## Bytes Defined 294 | 295 | Go has a raw data type called `byte` they are actually an alias to the `uint8` type. 296 | 297 | There are lots of ways to declare bytes 298 | 299 | .play examples/byte-declarations.go 300 | 301 | ## Byte Slices, Strings, and Runes 302 | 303 | ## Byte Slice 304 | 305 | It is the type most often used when dealing with IO operations. Or large sets of raw data. 306 | 307 | From `ioutil`: 308 | * `func ReadFile(filename string) ([]byte, error)` 309 | 310 | From `encoding/json`: 311 | * `func Marshal(v interface{}) ([]byte, error)` 312 | 313 | They are also the basic data type that underlies both `runes` and `strings`. 314 | 315 | ## Strings 316 | 317 | ## Strings are byte slices 318 | 319 | * Strings are actually backed by modified byte slices 320 | * Strings are passed by copy of their custom `sliceHeader` 321 | 322 | .play examples/strings-slice-comparison.go /^func main/,/^} 323 | 324 | ## Ok... Strings can be *thought of* as a byte slice 325 | 326 | Strings are Immutable, so they don't need a `cap` 327 | 328 | .code examples/strings-slice-comparison.txt 329 | 330 | .play examples/strings-slice-comparison.go /^func main/,/^} 331 | 332 | 333 | ## But what is the "true" size of a string? 334 | 335 | The size of the header + the length of the string: 336 | 337 | .play examples/strings-slice-comparison-2.go /^func main/,/^} 338 | 339 | ## What happens when I []byte a string? 340 | 341 | You make a copy! 342 | 343 | .play examples/strings-slice-comparison-3.go /^func main/,/^} 344 | 345 | ## String & []byte summary 346 | 347 | `string`: 348 | * Immutable 349 | * Less overhead 350 | * Can be `constant` 351 | * Ineffecient concat of large strings 352 | * Use `strings.Builder` for large string generation 353 | 354 | `[]byte`: 355 | * Can be modified/appended without full copy 356 | * More overhead 357 | * Lowest level IO 358 | 359 | ## String Indexing 360 | 361 | Because strings are like byte slices under the hood, they can be indexed. 362 | 363 | .play examples/strings-indexing.go /^func main/,/^} 364 | 365 | ## String Indexing - gotcha! 366 | 367 | Strings often contain non-ASII bytes: 368 | 369 | .play examples/strings-indexing-awry.go /^func main/,/^} 370 | 371 | ## String Indexing - Why did that happen? 372 | 373 | * strings are `[]byte` 374 | * non-ASCII characters are made up of multiple bytes 375 | 376 | .play examples/strings-indexing-awry-explained.go /^func main/,/^} 377 | 378 | **But how do we fix it?** 379 | 380 | ## Runes! 381 | 382 | * Runes are the default type used when creating a fuzzy constant with single quotes 383 | * Runes are an alias to the `int32` type 384 | 385 | .play examples/runes.go /^func main/,/^} 386 | 387 | ## Runes to Strings! 388 | 389 | We can explicitly convert them to strings to print: 390 | 391 | .play examples/runes-strings.go /^func main/,/^} 392 | 393 | ## Runes to Strings to Byte Slices! 394 | 395 | The go spec clearly defines how rune to string converson: 396 | 397 | .link https://golang.org/ref/spec#Conversions_to_and_from_a_string_type 398 | 399 | > 3. Converting a slice of runes to a string type yields a string that is the concatenation of the individual rune values converted to strings. 400 | 401 | So rune to string conversion is just appending the rune's bytes to the hidden `[]byte` behind a string. 402 | 403 | ## So that means we can do this: 404 | 405 | .play examples/runes-slice.go /^func main/,/^} 406 | 407 | ## Remember this? 408 | 409 | All this came around from our original indexing problem: 410 | 411 | .play examples/strings-indexing-awry-explained.go /^func main/,/^} 412 | 413 | ## String indexing - []rune 414 | 415 | You can convert to strings to `[]rune` to index 'characters' more reliably 416 | 417 | .play examples/strings-indexing-awry-fixed.go /^func main/,/^} 418 | 419 | ## String indexing - gotcha again! 420 | 421 | Strings don't always contain printable bytes. There is no requirement 422 | or guarantee that they will only have printable bytes. 423 | 424 | .play examples/strings-indexing-bytes.go /^func main/,/^} 425 | 426 | ## String looping 427 | 428 | .play examples/strings-loop.go /^func main/,/^} 429 | 430 | Remember: `string` is really `[]byte` 431 | 432 | ## Better string looping 433 | 434 | You must cast `string` to `[]rune` to iterate properly. 435 | 436 | .play examples/strings-loop-fixed.go /^func main/,/^} 437 | 438 | ## Even better 439 | 440 | The `range` operator is smart! It knows to do this for you! 441 | 442 | .play examples/strings-range.go /^func main/,/^} 443 | 444 | ## Even with NULL bytes 445 | 446 | .play examples/strings-range-null.go /^func main/,/^} 447 | 448 | ## Interesting Golang Type Discoveries 449 | 450 | 1. `bool` can be **more than one bit** 451 | 1. `int` and `uint` can **change size** 452 | 1. `floatXX` constants can have **fixed precision** 453 | 1. Constants can be **untyped** 454 | 1. `iota` is an `untyped int` and it **changes value** 455 | 1. All `slice` variables **cost the same** to shallow copy 456 | 1. Be careful when **indexing or looping** a `string` 457 | 458 | ## Structs 459 | 460 | Stucts are the way that go organizes data. 461 | 462 | They can have zero to N fields 463 | 464 | .play examples/structs.go /BEGIN OMIT/,/END OMIT/ 465 | 466 | ## They are usually as big as their fields combined 467 | 468 | .play examples/structs-sizes.go /^func main/,/^} 469 | 470 | ## Even when nested 471 | 472 | .play examples/structs-sizes-complex.go /^func main/,/^} 473 | 474 | ## But not always! 475 | 476 | .play examples/structs-sizes-padding.go /^func main/,/^} 477 | 478 | ## Go spec 479 | 480 | Explain that structs must be "naturally" alligned 481 | 482 | Go will pad the memory as needed in order to get struct fields to align along word boundries. 483 | 484 | Think of it as the complier doing this for you: 485 | 486 | .code examples/structs-sizes-padding-explained.go /^func main/,/^} 487 | 488 | : Basically, processor word size can be thought of as a "shovel size" where the system HAS to get enough data to fill the shovel all the time. So it's much more effecient on the system to ensure that data does not have to be fetched in uneven chunks. 489 | 490 | ## Struct sizes - padding natural alignment 491 | 492 | .play examples/structs-sizes-padding-alt.go /^func main/,/^} 493 | 494 | ## Struct sizes - padding bools 495 | 496 | .play examples/structs-sizes-padding-bools.go /^func main/,/^} 497 | 498 | ## Struct sizes - consecutive bools get packed 499 | 500 | .play examples/structs-sizes-padding-bools-more.go /^func main/,/^} 501 | 502 | ## Struct sizes - but only consecutive! 503 | 504 | .play examples/structs-sizes-padding-bools-more-awry.go /^func main/,/^} 505 | 506 | ## But what about empty stucts? 507 | 508 | `type nothin struct{}` 509 | 510 | How much space does that take? 511 | 512 | Is there a `structHeader`? 513 | 514 | ## Nope! Empty structs are zero size 515 | 516 | .play examples/empty-struct.go /^func main/,/^} 517 | 518 | ## Empty structs of all empty members are zero size 519 | 520 | .play examples/empty-struct-nested.go /^func main/,/^} 521 | 522 | ## Empty struct arrays are zero size 523 | 524 | .play examples/empty-struct-array.go /^func main/,/^} 525 | 526 | ## Empty struct slices are only as big as the sliceHeader 527 | 528 | .play examples/empty-struct-slice.go /^func main/,/^} 529 | 530 | ## The IMPORTANT part - Empty struct 531 | 532 | Empty structs are most practically used in maps and channels 533 | 534 | * This signals to the code reader that the *content* of the map or channel is not important. 535 | 536 | .play examples/empty-struct-use.go /^func main/,/^} 537 | 538 | * The memory savings in very large maps is also a nice bonus 539 | * Even `map[string]bool` wastes **8 bits** per entry 540 | 541 | ## Interesting Golang Type Discoveries 542 | 543 | 1. `bool` can be **more than one bit** 544 | 1. `int` and `uint` can **change size** 545 | 1. `floatXX` constants can have **fixed precision** 546 | 1. Constants can be **untyped** 547 | 1. `iota` is an `untyped int` and it **changes value** 548 | 1. All `slice` variables **cost the same** to shallow copy 549 | 1. Be careful when **indexing or looping** a `string` 550 | 1. Structs have **no overhead** but may have **padding** 551 | 552 | ## Maps 553 | 554 | ## Maps aren't a type 555 | 556 | No, really. 557 | 558 | They are very fancy structs that get generated for you at compile-time. All your map operations also get rewritten at that time: 559 | 560 | .code examples/maps-rewrite.txt 561 | 562 | .link https://dave.cheney.net/2018/05/29/how-the-go-runtime-implements-maps-efficiently-without-generics 563 | 564 | ## Interesting Golang Type Discoveries 565 | 566 | 1. `bool` can be **more than one bit** 567 | 1. `int` and `uint` can **change size** 568 | 1. `floatXX` constants can have **fixed precision** 569 | 1. Constants can be **untyped** 570 | 1. `iota` is an `untyped int` and it **changes value** 571 | 1. All `slice` variables **cost the same** to shallow copy 572 | 1. Be careful when **indexing or looping** a `string` 573 | 1. Structs have **no overhead** but may have **padding** 574 | 1. Maps **aren't a type** 575 | 576 | ## Interfaces 577 | 578 | ## Interfaces Defined 579 | 580 | Since Interfaces an hold anything, they have to be stored as two-word 581 | pairs of data: 582 | 583 | * A `uintptr` to information about the type stored in the interface 584 | * A `uintptr` to the associated data behind the type 585 | 586 | ## Interface sizes are always the same 587 | 588 | .play examples/interfaces.go /BEGIN OMIT/,/END OMIT/ 589 | 590 | ## Interfaces nil is not a nil 591 | 592 | .play examples/interfaces-nils.go /^func main/,/^} 593 | 594 | ## Interesting Golang Type Discoveries 595 | 596 | 1. `bool` can be **more than one bit** 597 | 1. `int` and `uint` can **change size** 598 | 1. `floatXX` constants can have **fixed precision** 599 | 1. Constants can be **untyped** 600 | 1. `iota` is an `untyped int` and it **changes value** 601 | 1. All `slice` variables **cost the same** to shallow copy 602 | 1. Be careful when **indexing or looping** a `string` 603 | 1. Structs have **no overhead** but may have **padding** 604 | 1. Maps **aren't a type** 605 | 1. Inteface `nil` **isn't a nil** 606 | 607 | ## Tools used for this presentation 608 | 609 | * `go present` 610 | 611 | .link https://godoc.org/golang.org/x/tools/present 612 | 613 | * Peek support for present files in `vscode` 614 | 615 | .link https://marketplace.visualstudio.com/items?itemName=carsonoid.vscode-go-present-peek 616 | -------------------------------------------------------------------------------- /theme/static/article.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: Helvetica, Arial, sans-serif; 4 | font-size: 16px; 5 | } 6 | pre, 7 | code { 8 | font-family: Menlo, monospace; 9 | font-size: 14px; 10 | } 11 | pre { 12 | line-height: 18px; 13 | margin: 0; 14 | padding: 0; 15 | } 16 | a { 17 | color: #375eab; 18 | text-decoration: none; 19 | } 20 | a:hover { 21 | text-decoration: underline; 22 | } 23 | p, 24 | ul, 25 | ol { 26 | margin: 20px; 27 | } 28 | 29 | h1, 30 | h2, 31 | h3, 32 | h4 { 33 | margin: 20px 0; 34 | padding: 0; 35 | color: #375eab; 36 | font-weight: bold; 37 | } 38 | h1 { 39 | font-size: 18px; 40 | padding: 2px 5px; 41 | } 42 | h2 { 43 | font-size: 16px; 44 | } 45 | h3 { 46 | font-size: 16px; 47 | } 48 | h3, 49 | h4 { 50 | margin: 20px 5px; 51 | } 52 | h4 { 53 | font-size: 16px; 54 | } 55 | 56 | div#heading { 57 | margin: 0 0 10px 0; 58 | padding: 21px 0; 59 | font-size: 20px; 60 | font-weight: bold; 61 | } 62 | 63 | div#heading .author { 64 | padding-top: 10px; 65 | font-size: 14px; 66 | font-weight: normal; 67 | } 68 | 69 | div#topbar { 70 | } 71 | 72 | body { 73 | text-align: center; 74 | } 75 | div#page { 76 | width: 100%; 77 | } 78 | div#page > .container, 79 | div#topbar > .container { 80 | text-align: left; 81 | margin-left: auto; 82 | margin-right: auto; 83 | padding: 0 20px; 84 | width: 900px; 85 | } 86 | div#page.wide > .container, 87 | div#topbar.wide > .container { 88 | width: auto; 89 | } 90 | 91 | div#footer { 92 | text-align: center; 93 | color: #666; 94 | font-size: 14px; 95 | margin: 40px 0; 96 | } 97 | 98 | .author p { 99 | margin: 0; 100 | padding: 0 20px; 101 | } 102 | 103 | div.code, 104 | div.output { 105 | margin: 20px 20px 20px 40px; 106 | -webkit-border-radius: 5px; 107 | -moz-border-radius: 5px; 108 | border-radius: 5px; 109 | } 110 | 111 | div.output { 112 | padding: 10px; 113 | } 114 | 115 | div.code { 116 | background: white; 117 | } 118 | div.output { 119 | background: black; 120 | } 121 | div.output .stdout { 122 | color: #e6e6e6; 123 | } 124 | div.output .stderr { 125 | color: rgb(244, 74, 63); 126 | } 127 | div.output .system { 128 | color: rgb(255, 209, 77); 129 | } 130 | 131 | .buttons { 132 | margin-left: 20px; 133 | } 134 | div.output .buttons { 135 | margin-left: 0; 136 | margin-bottom: 10px; 137 | } 138 | 139 | #toc { 140 | float: right; 141 | margin: 0px 10px; 142 | padding: 10px; 143 | border: 1px solid #e5ecf9; 144 | background-color: #eee; 145 | box-shadow: 3px 3px 2px #888888; 146 | 147 | max-width: 33%; 148 | 149 | -webkit-border-radius: 5px; 150 | -moz-border-radius: 5px; 151 | border-radius: 5px; 152 | } 153 | 154 | #tochead { 155 | font-weight: bold; 156 | font-variant: small-caps; 157 | font-size: 100%; 158 | text-align: center; 159 | padding-bottom: 5px; 160 | } 161 | 162 | #toc ul, 163 | #toc a { 164 | list-style-type: none; 165 | padding-left: 0px; 166 | color: black; 167 | margin: 0px; 168 | } 169 | 170 | ul.toc-inner a { 171 | padding-left: 10px !important; 172 | } 173 | 174 | @media print { 175 | .no-print, 176 | .no-print * { 177 | display: none !important; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /theme/static/dir.css: -------------------------------------------------------------------------------- 1 | /* copied from $GOROOT/doc/style.css */ 2 | 3 | body { 4 | margin: 0; 5 | font-family: Helvetica, Arial, sans-serif; 6 | font-size: 16px; 7 | } 8 | pre, 9 | code { 10 | font-family: Menlo, monospace; 11 | font-size: 14px; 12 | } 13 | pre { 14 | line-height: 18px; 15 | } 16 | pre .comment { 17 | color: #375eab; 18 | } 19 | pre .highlight, 20 | pre .highlight-comment, 21 | pre .selection-highlight, 22 | pre .selection-highlight-comment { 23 | background: #ffff00; 24 | } 25 | pre .selection, 26 | pre .selection-comment { 27 | background: #ff9632; 28 | } 29 | pre .ln { 30 | color: #999; 31 | } 32 | body { 33 | color: #222; 34 | } 35 | a, 36 | .exampleHeading .text { 37 | color: #375eab; 38 | text-decoration: none; 39 | } 40 | a:hover, 41 | .exampleHeading .text:hover { 42 | text-decoration: underline; 43 | } 44 | p, 45 | pre, 46 | ul, 47 | ol { 48 | margin: 20px; 49 | } 50 | pre { 51 | background: #e9e9e9; 52 | padding: 10px; 53 | 54 | -webkit-border-radius: 5px; 55 | -moz-border-radius: 5px; 56 | border-radius: 5px; 57 | } 58 | 59 | h1, 60 | h2, 61 | h3, 62 | h4, 63 | .rootHeading { 64 | margin: 20px 0; 65 | padding: 0; 66 | color: #375eab; 67 | font-weight: bold; 68 | } 69 | h1 { 70 | font-size: 24px; 71 | } 72 | h2 { 73 | font-size: 20px; 74 | background: #e0ebf5; 75 | padding: 2px 5px; 76 | } 77 | h3 { 78 | font-size: 20px; 79 | } 80 | h3, 81 | h4 { 82 | margin: 20px 5px; 83 | } 84 | h4 { 85 | font-size: 16px; 86 | } 87 | 88 | dl { 89 | margin: 20px; 90 | } 91 | dd { 92 | margin: 2px 20px; 93 | } 94 | dl, 95 | dd { 96 | font-size: 14px; 97 | } 98 | div#nav table td { 99 | vertical-align: top; 100 | } 101 | 102 | div#heading { 103 | float: left; 104 | margin: 0 0 10px 0; 105 | padding: 21px 0; 106 | font-size: 20px; 107 | font-weight: normal; 108 | } 109 | div#heading a { 110 | color: #222; 111 | text-decoration: none; 112 | } 113 | 114 | div#topbar { 115 | background: #e0ebf5; 116 | height: 64px; 117 | } 118 | 119 | body { 120 | text-align: center; 121 | } 122 | div#page, 123 | div#topbar > .container { 124 | clear: both; 125 | text-align: left; 126 | margin-left: auto; 127 | margin-right: auto; 128 | padding: 0 20px; 129 | width: 900px; 130 | } 131 | div#page.wide, 132 | div#topbar > .wide { 133 | width: auto; 134 | } 135 | div#plusone { 136 | float: right; 137 | } 138 | 139 | div#footer { 140 | color: #666; 141 | font-size: 14px; 142 | margin: 40px 0; 143 | } 144 | 145 | div#menu > a, 146 | div#menu > input { 147 | padding: 10px; 148 | 149 | text-decoration: none; 150 | font-size: 16px; 151 | 152 | -webkit-border-radius: 5px; 153 | -moz-border-radius: 5px; 154 | border-radius: 5px; 155 | } 156 | div#menu > a, 157 | div#menu > input { 158 | border: 1px solid #375eab; 159 | } 160 | div#menu > a { 161 | color: white; 162 | background: #375eab; 163 | } 164 | 165 | div#menu { 166 | float: right; 167 | min-width: 590px; 168 | padding: 10px 0; 169 | text-align: right; 170 | } 171 | div#menu > a { 172 | margin-right: 5px; 173 | margin-bottom: 10px; 174 | 175 | padding: 10px; 176 | } 177 | div#menu > input { 178 | position: relative; 179 | top: 1px; 180 | width: 60px; 181 | background: white; 182 | color: #222; 183 | } 184 | div#menu > input.inactive { 185 | color: #999; 186 | } 187 | -------------------------------------------------------------------------------- /theme/static/dir.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // copied from $GOROOT/doc/godocs.js 6 | 7 | function bindEvent(el, e, fn) { 8 | if (el.addEventListener) { 9 | el.addEventListener(e, fn, false); 10 | } else if (el.attachEvent) { 11 | el.attachEvent('on' + e, fn); 12 | } 13 | } 14 | 15 | function godocs_bindSearchEvents() { 16 | var search = document.getElementById('search'); 17 | if (!search) { 18 | // no search box (index disabled) 19 | return; 20 | } 21 | function clearInactive() { 22 | if (search.className == 'inactive') { 23 | search.value = ''; 24 | search.className = ''; 25 | } 26 | } 27 | function restoreInactive() { 28 | if (search.value !== '') { 29 | return; 30 | } 31 | if (search.type != 'search') { 32 | search.value = search.getAttribute('placeholder'); 33 | } 34 | search.className = 'inactive'; 35 | } 36 | restoreInactive(); 37 | bindEvent(search, 'focus', clearInactive); 38 | bindEvent(search, 'blur', restoreInactive); 39 | } 40 | 41 | bindEvent(window, 'load', godocs_bindSearchEvents); 42 | -------------------------------------------------------------------------------- /theme/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carsonoid/talk-gowest2020-go-types/7dce85f23ea3b2fbeac89bce4b470be72194bae5/theme/static/favicon.ico -------------------------------------------------------------------------------- /theme/static/jquery-ui.js: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.10.2 - 2013-03-20 2 | * http://jqueryui.com 3 | * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js 4 | * Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ 5 | 6 | (function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidthe.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery); -------------------------------------------------------------------------------- /theme/static/notes.css: -------------------------------------------------------------------------------- 1 | p { 2 | margin: 10px; 3 | } 4 | 5 | #presenter-slides { 6 | display: block; 7 | margin-top: -10px; 8 | margin-left: -17px; 9 | position: fixed; 10 | border: 0; 11 | width: 146%; 12 | height: 750px; 13 | 14 | transform: scale(0.7, 0.7); 15 | transform-origin: top left; 16 | -moz-transform: scale(0.7); 17 | -moz-transform-origin: top left; 18 | -o-transform: scale(0.7); 19 | -o-transform-origin: top left; 20 | -webkit-transform: scale(0.7); 21 | -webkit-transform-origin: top left; 22 | } 23 | 24 | #presenter-notes { 25 | margin-top: -180px; 26 | font-family: 'Open Sans', Arial, sans-serif; 27 | height: 30%; 28 | width: 100%; 29 | overflow: scroll; 30 | position: fixed; 31 | top: 706px; 32 | } 33 | -------------------------------------------------------------------------------- /theme/static/notes.js: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Store child window object which will display slides with notes 6 | var notesWindow = null; 7 | 8 | var isParentWindow = window.parent == window; 9 | 10 | // When parent window closes, clear storage and close child window 11 | if (isParentWindow) { 12 | window.onbeforeunload = function() { 13 | localStorage.clear(); 14 | if (notesWindow) notesWindow.close(); 15 | }; 16 | } 17 | 18 | function toggleNotesWindow() { 19 | if (!isParentWindow) return; 20 | if (notesWindow) { 21 | notesWindow.close(); 22 | notesWindow = null; 23 | return; 24 | } 25 | 26 | initNotes(); 27 | } 28 | 29 | // Create an unique key for the local storage so we don't mix the 30 | // destSlide of different presentations. For golang.org/issue/24688. 31 | function destSlideKey() { 32 | var key = ''; 33 | if (notesWindow) { 34 | var slides = notesWindow.document.getElementById('presenter-slides'); 35 | key = slides.src.split('#')[0]; 36 | } else { 37 | key = window.location.href.split('#')[0]; 38 | } 39 | return 'destSlide:' + key; 40 | } 41 | 42 | function initNotes() { 43 | notesWindow = window.open('', '', 'width=1000,height=700'); 44 | var w = notesWindow; 45 | var slidesUrl = window.location.href; 46 | 47 | // Hack to apply css. Requires existing html on notesWindow. 48 | w.document.write("
"); 49 | 50 | w.document.title = window.document.title; 51 | 52 | var slides = w.document.createElement('iframe'); 53 | slides.id = 'presenter-slides'; 54 | slides.src = slidesUrl; 55 | w.document.body.appendChild(slides); 56 | 57 | var curSlide = parseInt(localStorage.getItem(destSlideKey()), 10); 58 | var formattedNotes = ''; 59 | var section = sections[curSlide - 1]; 60 | // curSlide is 0 when initialized from the first page of slides. 61 | // Check if section is valid before retrieving Notes. 62 | if (section) { 63 | formattedNotes = formatNotes(section.Notes); 64 | } else if (curSlide == 0) { 65 | formattedNotes = formatNotes(titleNotes); 66 | } 67 | 68 | // setTimeout needed for Firefox 69 | setTimeout(function() { 70 | slides.focus(); 71 | }, 100); 72 | 73 | var notes = w.document.createElement('div'); 74 | notes.id = 'presenter-notes'; 75 | notes.innerHTML = formattedNotes; 76 | w.document.body.appendChild(notes); 77 | 78 | w.document.close(); 79 | 80 | function addPresenterNotesStyle() { 81 | var el = w.document.createElement('link'); 82 | el.rel = 'stylesheet'; 83 | el.type = 'text/css'; 84 | el.href = PERMANENT_URL_PREFIX + 'notes.css'; 85 | w.document.body.appendChild(el); 86 | w.document.querySelector('head').appendChild(el); 87 | } 88 | 89 | addPresenterNotesStyle(); 90 | 91 | // Add listener on notesWindow to update notes when triggered from 92 | // parent window 93 | w.addEventListener('storage', updateNotes, false); 94 | } 95 | 96 | function formatNotes(notes) { 97 | var formattedNotes = ''; 98 | if (notes) { 99 | for (var i = 0; i < notes.length; i++) { 100 | formattedNotes = formattedNotes + '

' + notes[i] + '

'; 101 | } 102 | } 103 | return formattedNotes; 104 | } 105 | 106 | function updateNotes() { 107 | // When triggered from parent window, notesWindow is null 108 | // The storage event listener on notesWindow will update notes 109 | if (!notesWindow) return; 110 | var destSlide = parseInt(localStorage.getItem(destSlideKey()), 10); 111 | var section = sections[destSlide - 1]; 112 | var el = notesWindow.document.getElementById('presenter-notes'); 113 | 114 | if (!el) return; 115 | 116 | if (section && section.Notes) { 117 | el.innerHTML = formatNotes(section.Notes); 118 | } else if (destSlide == 0) { 119 | el.innerHTML = formatNotes(titleNotes); 120 | } else { 121 | el.innerHTML = ''; 122 | } 123 | } 124 | 125 | /* Playground syncing */ 126 | 127 | // When presenter notes are enabled, playground click handlers are 128 | // stored here to sync click events on the correct playground 129 | var playgroundHandlers = { onRun: [], onKill: [], onClose: [] }; 130 | 131 | function updatePlay(e) { 132 | var i = localStorage.getItem('play-index'); 133 | 134 | switch (e.key) { 135 | case 'play-index': 136 | return; 137 | case 'play-action': 138 | // Sync 'run', 'kill', 'close' actions 139 | var action = localStorage.getItem('play-action'); 140 | playgroundHandlers[action][i](e); 141 | return; 142 | case 'play-code': 143 | // Sync code editing 144 | var play = document.querySelectorAll('div.playground')[i]; 145 | play.innerHTML = localStorage.getItem('play-code'); 146 | return; 147 | case 'output-style': 148 | // Sync resizing of playground output 149 | var out = document.querySelectorAll('.output')[i]; 150 | out.style = localStorage.getItem('output-style'); 151 | return; 152 | } 153 | } 154 | 155 | // Reset 'run', 'kill', 'close' storage items when synced 156 | // so that successive actions can be synced correctly 157 | function updatePlayStorage(action, index, e) { 158 | localStorage.setItem('play-index', index); 159 | 160 | if (localStorage.getItem('play-action') === action) { 161 | // We're the receiving window, and the message has been received 162 | localStorage.removeItem('play-action'); 163 | } else { 164 | // We're the triggering window, send the message 165 | localStorage.setItem('play-action', action); 166 | } 167 | 168 | if (action === 'onRun') { 169 | if (localStorage.getItem('play-shiftKey') === 'true') { 170 | localStorage.removeItem('play-shiftKey'); 171 | } else if (e.shiftKey) { 172 | localStorage.setItem('play-shiftKey', e.shiftKey); 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /theme/static/slides.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | var PERMANENT_URL_PREFIX = '/static/'; 6 | 7 | var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next']; 8 | 9 | var PM_TOUCH_SENSITIVITY = 15; 10 | 11 | var curSlide; 12 | 13 | /* ---------------------------------------------------------------------- */ 14 | /* classList polyfill by Eli Grey 15 | * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */ 16 | 17 | if ( 18 | typeof document !== 'undefined' && 19 | !('classList' in document.createElement('a')) 20 | ) { 21 | (function (view) { 22 | var classListProp = 'classList', 23 | protoProp = 'prototype', 24 | elemCtrProto = (view.HTMLElement || view.Element)[protoProp], 25 | objCtr = Object; 26 | (strTrim = 27 | String[protoProp].trim || 28 | function () { 29 | return this.replace(/^\s+|\s+$/g, ''); 30 | }), 31 | (arrIndexOf = 32 | Array[protoProp].indexOf || 33 | function (item) { 34 | for (var i = 0, len = this.length; i < len; i++) { 35 | if (i in this && this[i] === item) { 36 | return i; 37 | } 38 | } 39 | return -1; 40 | }), 41 | // Vendors: please allow content code to instantiate DOMExceptions 42 | (DOMEx = function (type, message) { 43 | this.name = type; 44 | this.code = DOMException[type]; 45 | this.message = message; 46 | }), 47 | (checkTokenAndGetIndex = function (classList, token) { 48 | if (token === '') { 49 | throw new DOMEx( 50 | 'SYNTAX_ERR', 51 | 'An invalid or illegal string was specified' 52 | ); 53 | } 54 | if (/\s/.test(token)) { 55 | throw new DOMEx( 56 | 'INVALID_CHARACTER_ERR', 57 | 'String contains an invalid character' 58 | ); 59 | } 60 | return arrIndexOf.call(classList, token); 61 | }), 62 | (ClassList = function (elem) { 63 | var trimmedClasses = strTrim.call(elem.className), 64 | classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []; 65 | for (var i = 0, len = classes.length; i < len; i++) { 66 | this.push(classes[i]); 67 | } 68 | this._updateClassName = function () { 69 | elem.className = this.toString(); 70 | }; 71 | }), 72 | (classListProto = ClassList[protoProp] = []), 73 | (classListGetter = function () { 74 | return new ClassList(this); 75 | }); 76 | // Most DOMException implementations don't allow calling DOMException's toString() 77 | // on non-DOMExceptions. Error's toString() is sufficient here. 78 | DOMEx[protoProp] = Error[protoProp]; 79 | classListProto.item = function (i) { 80 | return this[i] || null; 81 | }; 82 | classListProto.contains = function (token) { 83 | token += ''; 84 | return checkTokenAndGetIndex(this, token) !== -1; 85 | }; 86 | classListProto.add = function (token) { 87 | token += ''; 88 | if (checkTokenAndGetIndex(this, token) === -1) { 89 | this.push(token); 90 | this._updateClassName(); 91 | } 92 | }; 93 | classListProto.remove = function (token) { 94 | token += ''; 95 | var index = checkTokenAndGetIndex(this, token); 96 | if (index !== -1) { 97 | this.splice(index, 1); 98 | this._updateClassName(); 99 | } 100 | }; 101 | classListProto.toggle = function (token) { 102 | token += ''; 103 | if (checkTokenAndGetIndex(this, token) === -1) { 104 | this.add(token); 105 | } else { 106 | this.remove(token); 107 | } 108 | }; 109 | classListProto.toString = function () { 110 | return this.join(' '); 111 | }; 112 | 113 | if (objCtr.defineProperty) { 114 | var classListPropDesc = { 115 | get: classListGetter, 116 | enumerable: true, 117 | configurable: true, 118 | }; 119 | try { 120 | objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); 121 | } catch (ex) { 122 | // IE 8 doesn't support enumerable:true 123 | if (ex.number === -0x7ff5ec54) { 124 | classListPropDesc.enumerable = false; 125 | objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); 126 | } 127 | } 128 | } else if (objCtr[protoProp].__defineGetter__) { 129 | elemCtrProto.__defineGetter__(classListProp, classListGetter); 130 | } 131 | })(self); 132 | } 133 | /* ---------------------------------------------------------------------- */ 134 | 135 | /* Slide movement */ 136 | 137 | function hideHelpText() { 138 | document.getElementById('help').style.display = 'none'; 139 | } 140 | 141 | function getSlideEl(no) { 142 | if (no < 0 || no >= slideEls.length) { 143 | return null; 144 | } else { 145 | return slideEls[no]; 146 | } 147 | } 148 | 149 | function updateSlideClass(slideNo, className) { 150 | var el = getSlideEl(slideNo); 151 | 152 | if (!el) { 153 | return; 154 | } 155 | 156 | if (className) { 157 | el.classList.add(className); 158 | } 159 | 160 | for (var i in SLIDE_CLASSES) { 161 | if (className != SLIDE_CLASSES[i]) { 162 | el.classList.remove(SLIDE_CLASSES[i]); 163 | } 164 | } 165 | } 166 | 167 | function updateSlides() { 168 | if (window.trackPageview) window.trackPageview(); 169 | 170 | for (var i = 0; i < slideEls.length; i++) { 171 | switch (i) { 172 | case curSlide - 2: 173 | updateSlideClass(i, 'far-past'); 174 | break; 175 | case curSlide - 1: 176 | updateSlideClass(i, 'past'); 177 | break; 178 | case curSlide: 179 | updateSlideClass(i, 'current'); 180 | break; 181 | case curSlide + 1: 182 | updateSlideClass(i, 'next'); 183 | break; 184 | case curSlide + 2: 185 | updateSlideClass(i, 'far-next'); 186 | break; 187 | default: 188 | updateSlideClass(i); 189 | break; 190 | } 191 | } 192 | 193 | triggerLeaveEvent(curSlide - 1); 194 | triggerEnterEvent(curSlide); 195 | 196 | window.setTimeout(function () { 197 | // Hide after the slide 198 | disableSlideFrames(curSlide - 2); 199 | }, 301); 200 | 201 | enableSlideFrames(curSlide - 1); 202 | enableSlideFrames(curSlide + 2); 203 | 204 | updateHash(); 205 | } 206 | 207 | function prevSlide() { 208 | hideHelpText(); 209 | if (curSlide > 0) { 210 | curSlide--; 211 | 212 | updateSlides(); 213 | } 214 | 215 | if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide); 216 | } 217 | 218 | function nextSlide() { 219 | hideHelpText(); 220 | if (curSlide < slideEls.length - 1) { 221 | curSlide++; 222 | 223 | updateSlides(); 224 | } 225 | 226 | if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide); 227 | } 228 | 229 | /* Slide events */ 230 | 231 | function triggerEnterEvent(no) { 232 | var el = getSlideEl(no); 233 | if (!el) { 234 | return; 235 | } 236 | 237 | var onEnter = el.getAttribute('onslideenter'); 238 | if (onEnter) { 239 | new Function(onEnter).call(el); 240 | } 241 | 242 | var evt = document.createEvent('Event'); 243 | evt.initEvent('slideenter', true, true); 244 | evt.slideNumber = no + 1; // Make it readable 245 | 246 | el.dispatchEvent(evt); 247 | } 248 | 249 | function triggerLeaveEvent(no) { 250 | var el = getSlideEl(no); 251 | if (!el) { 252 | return; 253 | } 254 | 255 | var onLeave = el.getAttribute('onslideleave'); 256 | if (onLeave) { 257 | new Function(onLeave).call(el); 258 | } 259 | 260 | var evt = document.createEvent('Event'); 261 | evt.initEvent('slideleave', true, true); 262 | evt.slideNumber = no + 1; // Make it readable 263 | 264 | el.dispatchEvent(evt); 265 | } 266 | 267 | /* Touch events */ 268 | 269 | function handleTouchStart(event) { 270 | if (event.touches.length == 1) { 271 | touchDX = 0; 272 | touchDY = 0; 273 | 274 | touchStartX = event.touches[0].pageX; 275 | touchStartY = event.touches[0].pageY; 276 | 277 | document.body.addEventListener('touchmove', handleTouchMove, true); 278 | document.body.addEventListener('touchend', handleTouchEnd, true); 279 | } 280 | } 281 | 282 | function handleTouchMove(event) { 283 | if (event.touches.length > 1) { 284 | cancelTouch(); 285 | } else { 286 | touchDX = event.touches[0].pageX - touchStartX; 287 | touchDY = event.touches[0].pageY - touchStartY; 288 | event.preventDefault(); 289 | } 290 | } 291 | 292 | function handleTouchEnd(event) { 293 | var dx = Math.abs(touchDX); 294 | var dy = Math.abs(touchDY); 295 | 296 | if (dx > PM_TOUCH_SENSITIVITY && dy < (dx * 2) / 3) { 297 | if (touchDX > 0) { 298 | prevSlide(); 299 | } else { 300 | nextSlide(); 301 | } 302 | } 303 | 304 | cancelTouch(); 305 | } 306 | 307 | function cancelTouch() { 308 | document.body.removeEventListener('touchmove', handleTouchMove, true); 309 | document.body.removeEventListener('touchend', handleTouchEnd, true); 310 | } 311 | 312 | /* Preloading frames */ 313 | 314 | function disableSlideFrames(no) { 315 | var el = getSlideEl(no); 316 | if (!el) { 317 | return; 318 | } 319 | 320 | var frames = el.getElementsByTagName('iframe'); 321 | for (var i = 0, frame; (frame = frames[i]); i++) { 322 | disableFrame(frame); 323 | } 324 | } 325 | 326 | function enableSlideFrames(no) { 327 | var el = getSlideEl(no); 328 | if (!el) { 329 | return; 330 | } 331 | 332 | var frames = el.getElementsByTagName('iframe'); 333 | for (var i = 0, frame; (frame = frames[i]); i++) { 334 | enableFrame(frame); 335 | } 336 | } 337 | 338 | function disableFrame(frame) { 339 | frame.src = 'about:blank'; 340 | } 341 | 342 | function enableFrame(frame) { 343 | var src = frame._src; 344 | 345 | if (frame.src != src && src != 'about:blank') { 346 | frame.src = src; 347 | } 348 | } 349 | 350 | function setupFrames() { 351 | var frames = document.querySelectorAll('iframe'); 352 | for (var i = 0, frame; (frame = frames[i]); i++) { 353 | frame._src = frame.src; 354 | disableFrame(frame); 355 | } 356 | 357 | enableSlideFrames(curSlide); 358 | enableSlideFrames(curSlide + 1); 359 | enableSlideFrames(curSlide + 2); 360 | } 361 | 362 | function setupInteraction() { 363 | /* Clicking and tapping */ 364 | 365 | var el = document.createElement('div'); 366 | el.className = 'slide-area'; 367 | el.id = 'prev-slide-area'; 368 | el.addEventListener('click', prevSlide, false); 369 | document.querySelector('section.slides').appendChild(el); 370 | 371 | var el = document.createElement('div'); 372 | el.className = 'slide-area'; 373 | el.id = 'next-slide-area'; 374 | el.addEventListener('click', nextSlide, false); 375 | document.querySelector('section.slides').appendChild(el); 376 | 377 | /* Swiping */ 378 | 379 | document.body.addEventListener('touchstart', handleTouchStart, false); 380 | } 381 | 382 | /* Hash functions */ 383 | 384 | function getCurSlideFromHash() { 385 | var slideNo = parseInt(location.hash.substr(1)); 386 | 387 | if (slideNo) { 388 | curSlide = slideNo - 1; 389 | } else { 390 | curSlide = 0; 391 | } 392 | } 393 | 394 | function updateHash() { 395 | location.replace('#' + (curSlide + 1)); 396 | } 397 | 398 | /* Event listeners */ 399 | 400 | function handleBodyKeyDown(event) { 401 | // If we're in a code element, only handle pgup/down. 402 | var inCode = event.target.classList.contains('code'); 403 | 404 | switch (event.keyCode) { 405 | case 78: // 'N' opens presenter notes window 406 | if (!inCode && notesEnabled) toggleNotesWindow(); 407 | break; 408 | case 72: // 'H' hides the help text 409 | case 27: // escape key 410 | if (!inCode) hideHelpText(); 411 | break; 412 | 413 | case 39: // right arrow 414 | case 13: // Enter 415 | case 32: // space 416 | if (inCode) break; 417 | case 34: // PgDn 418 | nextSlide(); 419 | event.preventDefault(); 420 | break; 421 | 422 | case 37: // left arrow 423 | case 8: // Backspace 424 | if (inCode) break; 425 | case 33: // PgUp 426 | prevSlide(); 427 | event.preventDefault(); 428 | break; 429 | 430 | case 40: // down arrow 431 | if (inCode) break; 432 | nextSlide(); 433 | event.preventDefault(); 434 | break; 435 | 436 | case 38: // up arrow 437 | if (inCode) break; 438 | prevSlide(); 439 | event.preventDefault(); 440 | break; 441 | } 442 | } 443 | 444 | function scaleSmallViewports() { 445 | var el = document.querySelector('section.slides'); 446 | var transform = ''; 447 | var sWidthPx = 1250; 448 | var sHeightPx = 750; 449 | var sAspectRatio = sWidthPx / sHeightPx; 450 | var wAspectRatio = window.innerWidth / window.innerHeight; 451 | 452 | if (wAspectRatio <= sAspectRatio && window.innerWidth < sWidthPx) { 453 | transform = 'scale(' + window.innerWidth / sWidthPx + ')'; 454 | } else if (window.innerHeight < sHeightPx) { 455 | transform = 'scale(' + window.innerHeight / sHeightPx + ')'; 456 | } 457 | el.style.transform = transform; 458 | } 459 | 460 | function addEventListeners() { 461 | document.addEventListener('keydown', handleBodyKeyDown, false); 462 | var resizeTimeout; 463 | window.addEventListener('resize', function () { 464 | // throttle resize events 465 | window.clearTimeout(resizeTimeout); 466 | resizeTimeout = window.setTimeout(function () { 467 | resizeTimeout = null; 468 | scaleSmallViewports(); 469 | }, 50); 470 | }); 471 | 472 | // Force reset transform property of section.slides when printing page. 473 | // Use both onbeforeprint and matchMedia for compatibility with different browsers. 474 | var beforePrint = function () { 475 | var el = document.querySelector('section.slides'); 476 | el.style.transform = ''; 477 | }; 478 | window.onbeforeprint = beforePrint; 479 | if (window.matchMedia) { 480 | var mediaQueryList = window.matchMedia('print'); 481 | mediaQueryList.addListener(function (mql) { 482 | if (mql.matches) beforePrint(); 483 | }); 484 | } 485 | } 486 | 487 | /* Initialization */ 488 | 489 | function addFontStyle() { 490 | var el = document.createElement('link'); 491 | el.rel = 'stylesheet'; 492 | el.type = 'text/css'; 493 | el.href = 494 | '//fonts.googleapis.com/css?family=' + 495 | 'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono'; 496 | 497 | document.body.appendChild(el); 498 | } 499 | 500 | function addGeneralStyle() { 501 | var el = document.createElement('link'); 502 | el.rel = 'stylesheet'; 503 | el.type = 'text/css'; 504 | el.href = PERMANENT_URL_PREFIX + 'styles.css'; 505 | document.body.appendChild(el); 506 | 507 | var el = document.createElement('meta'); 508 | el.name = 'viewport'; 509 | el.content = 'width=device-width,height=device-height,initial-scale=1'; 510 | document.querySelector('head').appendChild(el); 511 | 512 | var el = document.createElement('meta'); 513 | el.name = 'apple-mobile-web-app-capable'; 514 | el.content = 'yes'; 515 | document.querySelector('head').appendChild(el); 516 | 517 | scaleSmallViewports(); 518 | } 519 | 520 | function handleDomLoaded() { 521 | slideEls = document.querySelectorAll('section.slides > article'); 522 | 523 | setupFrames(); 524 | 525 | addFontStyle(); 526 | addGeneralStyle(); 527 | addEventListeners(); 528 | 529 | updateSlides(); 530 | 531 | setupInteraction(); 532 | 533 | if ( 534 | window.location.hostname == 'localhost' || 535 | window.location.hostname == '127.0.0.1' || 536 | window.location.hostname == '::1' 537 | ) { 538 | hideHelpText(); 539 | } 540 | 541 | document.body.classList.add('loaded'); 542 | 543 | setupNotesSync(); 544 | } 545 | 546 | function initialize() { 547 | getCurSlideFromHash(); 548 | 549 | if (window['_DEBUG']) { 550 | PERMANENT_URL_PREFIX = '../'; 551 | } 552 | 553 | if (window['_DCL']) { 554 | handleDomLoaded(); 555 | } else { 556 | document.addEventListener('DOMContentLoaded', handleDomLoaded, false); 557 | } 558 | } 559 | 560 | // If ?debug exists then load the script relative instead of absolute 561 | if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) { 562 | document.addEventListener( 563 | 'DOMContentLoaded', 564 | function () { 565 | // Avoid missing the DomContentLoaded event 566 | window['_DCL'] = true; 567 | }, 568 | false 569 | ); 570 | 571 | window['_DEBUG'] = true; 572 | var script = document.createElement('script'); 573 | script.type = 'text/javascript'; 574 | script.src = '../slides.js'; 575 | var s = document.getElementsByTagName('script')[0]; 576 | s.parentNode.insertBefore(script, s); 577 | 578 | // Remove this script 579 | s.parentNode.removeChild(s); 580 | } else { 581 | initialize(); 582 | } 583 | 584 | /* Synchronize windows when notes are enabled */ 585 | 586 | function setupNotesSync() { 587 | if (!notesEnabled) return; 588 | 589 | function setupPlayResizeSync() { 590 | var out = document.getElementsByClassName('output'); 591 | for (var i = 0; i < out.length; i++) { 592 | $(out[i]).bind('resize', function (event) { 593 | if ($(event.target).hasClass('ui-resizable')) { 594 | localStorage.setItem('play-index', i); 595 | localStorage.setItem('output-style', out[i].style.cssText); 596 | } 597 | }); 598 | } 599 | } 600 | function setupPlayCodeSync() { 601 | var play = document.querySelectorAll('div.playground'); 602 | for (var i = 0; i < play.length; i++) { 603 | play[i].addEventListener('input', inputHandler, false); 604 | 605 | function inputHandler(e) { 606 | localStorage.setItem('play-index', i); 607 | localStorage.setItem('play-code', e.target.innerHTML); 608 | } 609 | } 610 | } 611 | 612 | setupPlayCodeSync(); 613 | setupPlayResizeSync(); 614 | localStorage.setItem(destSlideKey(), curSlide); 615 | window.addEventListener('storage', updateOtherWindow, false); 616 | } 617 | 618 | // An update to local storage is caught only by the other window 619 | // The triggering window does not handle any sync actions 620 | function updateOtherWindow(e) { 621 | // Ignore remove storage events which are not meant to update the other window 622 | var isRemoveStorageEvent = !e.newValue; 623 | if (isRemoveStorageEvent) return; 624 | 625 | var destSlide = localStorage.getItem(destSlideKey()); 626 | while (destSlide > curSlide) { 627 | nextSlide(); 628 | } 629 | while (destSlide < curSlide) { 630 | prevSlide(); 631 | } 632 | 633 | updatePlay(e); 634 | updateNotes(); 635 | } 636 | -------------------------------------------------------------------------------- /theme/static/styles.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | /* Framework */ 3 | html { 4 | height: 100%; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | padding: 0; 10 | 11 | display: block !important; 12 | 13 | height: 100%; 14 | height: 100vh; 15 | 16 | overflow: hidden; 17 | 18 | background: rgb(215, 215, 215); 19 | background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 20 | background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 21 | background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 22 | background: -webkit-gradient( 23 | radial, 24 | 50% 50%, 25 | 0, 26 | 50% 50%, 27 | 500, 28 | from(rgb(240, 240, 240)), 29 | to(rgb(190, 190, 190)) 30 | ); 31 | 32 | -webkit-font-smoothing: antialiased; 33 | } 34 | 35 | .slides { 36 | width: 100%; 37 | height: 100%; 38 | left: 0; 39 | top: 0; 40 | 41 | position: absolute; 42 | 43 | -webkit-transform: translate3d(0, 0, 0); 44 | } 45 | 46 | .slides > article { 47 | display: block; 48 | 49 | position: absolute; 50 | overflow: hidden; 51 | 52 | width: 900px; 53 | height: 700px; 54 | 55 | left: 50%; 56 | top: 50%; 57 | 58 | margin-left: -450px; 59 | margin-top: -350px; 60 | 61 | padding: 40px 60px; 62 | 63 | box-sizing: border-box; 64 | -o-box-sizing: border-box; 65 | -moz-box-sizing: border-box; 66 | -webkit-box-sizing: border-box; 67 | 68 | border-radius: 10px; 69 | -o-border-radius: 10px; 70 | -moz-border-radius: 10px; 71 | -webkit-border-radius: 10px; 72 | 73 | background-color: white; 74 | 75 | border: 1px solid rgba(0, 0, 0, 0.3); 76 | 77 | transition: transform 0.3s ease-out; 78 | -o-transition: -o-transform 0.3s ease-out; 79 | -moz-transition: -moz-transform 0.3s ease-out; 80 | -webkit-transition: -webkit-transform 0.3s ease-out; 81 | } 82 | .slides.layout-widescreen > article { 83 | /* margin-left: -550px; 84 | width: 1500px; */ 85 | } 86 | .slides.layout-faux-widescreen > article { 87 | margin-left: -550px; 88 | width: 1100px; 89 | 90 | padding: 40px 160px; 91 | } 92 | 93 | .slides.layout-widescreen > article:not(.nobackground):not(.biglogo), 94 | .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) { 95 | background-position-x: 0, 840px; 96 | } 97 | 98 | /* Clickable/tappable areas */ 99 | 100 | .slide-area { 101 | z-index: 1000; 102 | 103 | position: absolute; 104 | left: 0; 105 | top: 0; 106 | width: 150px; 107 | height: 700px; 108 | 109 | left: 50%; 110 | top: 50%; 111 | 112 | cursor: pointer; 113 | margin-top: -350px; 114 | 115 | tap-highlight-color: transparent; 116 | -o-tap-highlight-color: transparent; 117 | -moz-tap-highlight-color: transparent; 118 | -webkit-tap-highlight-color: transparent; 119 | } 120 | #prev-slide-area { 121 | margin-left: -550px; 122 | } 123 | #next-slide-area { 124 | margin-left: 400px; 125 | } 126 | .slides.layout-widescreen #prev-slide-area, 127 | .slides.layout-faux-widescreen #prev-slide-area { 128 | margin-left: -650px; 129 | } 130 | .slides.layout-widescreen #next-slide-area, 131 | .slides.layout-faux-widescreen #next-slide-area { 132 | margin-left: 500px; 133 | } 134 | 135 | /* Slides */ 136 | 137 | .slides > article { 138 | display: none; 139 | } 140 | .slides > article.far-past { 141 | display: block; 142 | transform: translate(-2040px); 143 | -o-transform: translate(-2040px); 144 | -moz-transform: translate(-2040px); 145 | -webkit-transform: translate3d(-2040px, 0, 0); 146 | } 147 | .slides > article.past { 148 | display: block; 149 | transform: translate(-1020px); 150 | -o-transform: translate(-1020px); 151 | -moz-transform: translate(-1020px); 152 | -webkit-transform: translate3d(-1020px, 0, 0); 153 | } 154 | .slides > article.current { 155 | display: block; 156 | transform: translate(0); 157 | -o-transform: translate(0); 158 | -moz-transform: translate(0); 159 | -webkit-transform: translate3d(0, 0, 0); 160 | } 161 | .slides > article.next { 162 | display: block; 163 | transform: translate(1020px); 164 | -o-transform: translate(1020px); 165 | -moz-transform: translate(1020px); 166 | -webkit-transform: translate3d(1020px, 0, 0); 167 | } 168 | .slides > article.far-next { 169 | display: block; 170 | transform: translate(2040px); 171 | -o-transform: translate(2040px); 172 | -moz-transform: translate(2040px); 173 | -webkit-transform: translate3d(2040px, 0, 0); 174 | } 175 | 176 | .slides.layout-widescreen > article.far-past, 177 | .slides.layout-faux-widescreen > article.far-past { 178 | display: block; 179 | transform: translate(-2260px); 180 | -o-transform: translate(-2260px); 181 | -moz-transform: translate(-2260px); 182 | -webkit-transform: translate3d(-2260px, 0, 0); 183 | } 184 | .slides.layout-widescreen > article.past, 185 | .slides.layout-faux-widescreen > article.past { 186 | display: block; 187 | transform: translate(-1130px); 188 | -o-transform: translate(-1130px); 189 | -moz-transform: translate(-1130px); 190 | -webkit-transform: translate3d(-1130px, 0, 0); 191 | } 192 | .slides.layout-widescreen > article.current, 193 | .slides.layout-faux-widescreen > article.current { 194 | display: block; 195 | transform: translate(0); 196 | -o-transform: translate(0); 197 | -moz-transform: translate(0); 198 | -webkit-transform: translate3d(0, 0, 0); 199 | } 200 | .slides.layout-widescreen > article.next, 201 | .slides.layout-faux-widescreen > article.next { 202 | display: block; 203 | transform: translate(1130px); 204 | -o-transform: translate(1130px); 205 | -moz-transform: translate(1130px); 206 | -webkit-transform: translate3d(1130px, 0, 0); 207 | } 208 | .slides.layout-widescreen > article.far-next, 209 | .slides.layout-faux-widescreen > article.far-next { 210 | display: block; 211 | transform: translate(2260px); 212 | -o-transform: translate(2260px); 213 | -moz-transform: translate(2260px); 214 | -webkit-transform: translate3d(2260px, 0, 0); 215 | } 216 | } 217 | 218 | @media print { 219 | /* Set page layout */ 220 | @page { 221 | size: A4 landscape; 222 | } 223 | 224 | body { 225 | display: block !important; 226 | } 227 | 228 | .slides > article { 229 | display: block; 230 | 231 | position: relative; 232 | 233 | page-break-inside: never; 234 | page-break-after: always; 235 | 236 | overflow: hidden; 237 | } 238 | 239 | h2 { 240 | position: static !important; 241 | margin-top: 400px !important; 242 | margin-bottom: 100px !important; 243 | } 244 | 245 | div.code { 246 | background: rgb(240, 240, 240); 247 | } 248 | 249 | /* Add explicit links */ 250 | a:link:after, 251 | a:visited:after { 252 | content: ' (' attr(href) ') '; 253 | font-size: 50%; 254 | } 255 | 256 | #help { 257 | display: none; 258 | visibility: hidden; 259 | } 260 | } 261 | 262 | /* Styles for full screen mode */ 263 | .slides.fullscreen > article.next, .slides.fullscreen > article.far-next, 264 | .slides.fullscreen > article.past, .slides.fullscreen > article.far-past { 265 | display: none; 266 | } 267 | 268 | /* Styles for slides */ 269 | 270 | .slides > article { 271 | font-family: 'Open Sans', Arial, sans-serif; 272 | 273 | color: black; 274 | text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); 275 | 276 | font-size: 26px; 277 | line-height: 36px; 278 | 279 | letter-spacing: -1px; 280 | } 281 | 282 | b { 283 | font-weight: 600; 284 | } 285 | 286 | a { 287 | color: rgb(0, 102, 204); 288 | text-decoration: none; 289 | } 290 | a:visited { 291 | color: rgba(0, 102, 204, 0.75); 292 | } 293 | a:hover { 294 | color: black; 295 | } 296 | 297 | p { 298 | margin: 0; 299 | padding: 0; 300 | 301 | margin-top: 20px; 302 | } 303 | p:first-child { 304 | margin-top: 0; 305 | } 306 | 307 | h1 { 308 | font-size: 60px; 309 | line-height: 60px; 310 | 311 | padding: 0; 312 | margin: 0; 313 | margin-top: 200px; 314 | margin-bottom: 5px; 315 | padding-right: 40px; 316 | 317 | font-weight: 600; 318 | 319 | letter-spacing: -3px; 320 | 321 | color: rgb(51, 51, 51); 322 | } 323 | 324 | h2 { 325 | font-size: 45px; 326 | line-height: 45px; 327 | 328 | position: absolute; 329 | bottom: 150px; 330 | 331 | padding: 0; 332 | margin: 0; 333 | padding-right: 40px; 334 | 335 | font-weight: 600; 336 | 337 | letter-spacing: -2px; 338 | 339 | color: rgb(51, 51, 51); 340 | } 341 | 342 | h3 { 343 | font-size: 30px; 344 | line-height: 36px; 345 | 346 | padding: 0; 347 | margin: 0; 348 | padding-right: 40px; 349 | 350 | font-weight: 600; 351 | 352 | letter-spacing: -1px; 353 | 354 | color: rgb(51, 51, 51); 355 | } 356 | 357 | ul { 358 | margin: 0; 359 | padding: 0; 360 | margin-top: 20px; 361 | margin-left: 1.5em; 362 | } 363 | li { 364 | padding: 0; 365 | margin: 0 0 0.5em 0; 366 | } 367 | 368 | div.code { 369 | padding: 5px 10px; 370 | margin-top: 20px; 371 | margin-bottom: 20px; 372 | overflow: hidden; 373 | 374 | background: rgb(240, 240, 240); 375 | border: 1px solid rgb(224, 224, 224); 376 | } 377 | pre { 378 | margin: 0; 379 | padding: 0; 380 | 381 | font-family: 'Droid Sans Mono', 'Courier New', monospace; 382 | font-size: 18px; 383 | line-height: 24px; 384 | letter-spacing: -1px; 385 | 386 | color: black; 387 | } 388 | 389 | pre.numbers span:before { 390 | content: attr(num); 391 | margin-right: 1em; 392 | display: inline-block; 393 | } 394 | 395 | code { 396 | font-size: 95%; 397 | font-family: 'Droid Sans Mono', 'Courier New', monospace; 398 | 399 | padding: .2em .4em; 400 | margin: 0; 401 | font-size: 85%; 402 | background-color: rgba(27,31,35,.05); 403 | border-radius: 6px; 404 | } 405 | 406 | article > .image, 407 | article > .video { 408 | text-align: center; 409 | margin-top: 40px; 410 | } 411 | 412 | article.background { 413 | background-size: contain; 414 | background-repeat: round; 415 | } 416 | 417 | table { 418 | width: 100%; 419 | border-collapse: collapse; 420 | margin-top: 40px; 421 | } 422 | th { 423 | font-weight: 600; 424 | text-align: left; 425 | } 426 | td, 427 | th { 428 | border: 1px solid rgb(224, 224, 224); 429 | padding: 5px 10px; 430 | vertical-align: top; 431 | } 432 | 433 | p.link { 434 | margin-left: 20px; 435 | } 436 | 437 | .pagenumber { 438 | color: #8c8c8c; 439 | font-size: 75%; 440 | position: absolute; 441 | bottom: 0px; 442 | right: 10px; 443 | } 444 | 445 | /* Code */ 446 | div.code { 447 | outline: 0px solid transparent; 448 | } 449 | div.playground { 450 | position: relative; 451 | } 452 | div.output { 453 | position: absolute; 454 | left: 50%; 455 | top: 50%; 456 | right: 40px; 457 | bottom: 40px; 458 | background: #202020; 459 | padding: 5px 10px; 460 | z-index: 2; 461 | 462 | border-radius: 10px; 463 | -o-border-radius: 10px; 464 | -moz-border-radius: 10px; 465 | -webkit-border-radius: 10px; 466 | } 467 | div.output pre { 468 | margin: 0; 469 | padding: 0; 470 | background: none; 471 | border: none; 472 | width: 100%; 473 | height: 100%; 474 | overflow: auto; 475 | } 476 | div.output .stdout, 477 | div.output pre { 478 | color: #e6e6e6; 479 | } 480 | div.output .stderr, 481 | div.output .error { 482 | color: rgb(255, 200, 200); 483 | } 484 | div.output .system, 485 | div.output .exit { 486 | color: rgb(255, 230, 120); 487 | } 488 | .buttons { 489 | position: relative; 490 | float: right; 491 | top: -60px; 492 | right: 10px; 493 | } 494 | div.output .buttons { 495 | position: absolute; 496 | float: none; 497 | top: auto; 498 | right: 5px; 499 | bottom: 5px; 500 | } 501 | 502 | /* Presenter details */ 503 | .presenter { 504 | margin-top: 20px; 505 | } 506 | .presenter p, 507 | .presenter .link { 508 | margin: 0; 509 | font-size: 28px; 510 | line-height: 1.2em; 511 | } 512 | 513 | /* Output resize details */ 514 | .ui-resizable-handle { 515 | position: absolute; 516 | } 517 | .ui-resizable-n { 518 | cursor: n-resize; 519 | height: 7px; 520 | width: 100%; 521 | top: -5px; 522 | left: 0; 523 | } 524 | .ui-resizable-w { 525 | cursor: w-resize; 526 | width: 7px; 527 | left: -5px; 528 | top: 0; 529 | height: 100%; 530 | } 531 | .ui-resizable-nw { 532 | cursor: nw-resize; 533 | width: 9px; 534 | height: 9px; 535 | left: -5px; 536 | top: -5px; 537 | } 538 | iframe { 539 | border: none; 540 | } 541 | figcaption { 542 | color: #666; 543 | text-align: center; 544 | font-size: 0.75em; 545 | } 546 | 547 | #help { 548 | font-family: 'Open Sans', Arial, sans-serif; 549 | text-align: center; 550 | color: white; 551 | background: #000; 552 | opacity: 0.5; 553 | position: fixed; 554 | bottom: 25px; 555 | left: 50px; 556 | right: 50px; 557 | padding: 20px; 558 | 559 | border-radius: 10px; 560 | -o-border-radius: 10px; 561 | -moz-border-radius: 10px; 562 | -webkit-border-radius: 10px; 563 | } 564 | 565 | .slide-area { 566 | display: none; 567 | } 568 | 569 | .emphasize { 570 | color: red; 571 | font-weight: bold; 572 | } 573 | 574 | blockquote { 575 | background: #f9f9f9; 576 | border-left: 10px solid #ccc; 577 | margin: 1.5em 10px; 578 | padding: 0.5em 10px; 579 | } 580 | blockquote:before { 581 | color: #ccc; 582 | font-size: 4em; 583 | line-height: 0.1em; 584 | margin-right: 0.25em; 585 | vertical-align: -0.4em; 586 | } 587 | blockquote p { 588 | display: inline; 589 | } 590 | -------------------------------------------------------------------------------- /theme/templates/action.tmpl: -------------------------------------------------------------------------------- 1 | {/* 2 | This is the action template. 3 | It determines how the formatting actions are rendered. 4 | */} 5 | 6 | {{define "section"}} 7 | {{.FormattedNumber}} {{.Title}} 8 | {{range .Elem}}{{elem $.Template .}}{{end}} 9 | {{end}} 10 | 11 | {{define "list"}} 12 |
    13 | {{range .Bullet}} 14 |
  • {{style .}}
  • 15 | {{end}} 16 |
17 | {{end}} 18 | 19 | {{define "text"}} 20 | {{if .Pre}} 21 |
{{range .Lines}}{{.}}{{end}}
22 | {{else}} 23 |

24 | {{range $i, $l := .Lines}}{{if $i}}{{template "newline"}} 25 | {{end}}{{style $l}}{{end}} 26 |

27 | {{end}} 28 | {{end}} 29 | 30 | {{define "code"}} 31 |
{{.Text}}
32 | {{end}} 33 | 34 | {{define "image"}} 35 |
36 | 37 |
38 | {{end}} 39 | 40 | {{define "video"}} 41 |
42 | 45 |
46 | {{end}} 47 | 48 | {{define "background"}} 49 |
50 | 51 |
52 | {{end}} 53 | 54 | {{define "iframe"}} 55 | 56 | {{end}} 57 | 58 | {{define "link"}}
{{end}} 59 | 60 | {{define "html"}}{{.HTML}}{{end}} 61 | 62 | {{define "caption"}}
{{style .Text}}
{{end}} 63 | -------------------------------------------------------------------------------- /theme/templates/article.tmpl: -------------------------------------------------------------------------------- 1 | {/* This is the article template. It defines how articles are formatted. */} 2 | 3 | {{define "root"}} 4 | 5 | 6 | 7 | {{.Title}} 8 | 9 | 10 | 27 | 28 | 29 | 30 |
31 |
32 |
{{.Title}} 33 | {{with .Subtitle}}{{.}}{{end}} 34 | {{if .Authors}} 35 | {{range .Authors}} 36 |
37 | {{range .Elem}}{{elem $.Template .}}{{end}} 38 |
39 | {{end}} 40 | {{end}} 41 |
42 |
43 |
44 |
45 |
46 | {{with .Sections}} 47 |
48 |
Contents
49 | {{template "TOC" .}} 50 |
51 | {{end}} 52 | 53 | {{range .Sections}} 54 | {{elem $.Template .}} 55 | {{end}}{{/* of Section block */}} 56 | 57 |
58 |
59 | 60 | {{if .PlayEnabled}} 61 | 62 | {{end}} 63 | 64 | 74 | 75 | 76 | {{end}} 77 | 78 | {{define "TOC"}} 79 | 85 | {{end}} 86 | 87 | {{define "TOC-Inner"}} 88 | 94 | {{end}} 95 | 96 | {{define "newline"}} 97 | {{/* No automatic line break. Paragraphs are free-form. */}} 98 | {{end}} 99 | -------------------------------------------------------------------------------- /theme/templates/dir.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Talks - The Go Programming Language 6 | 7 | 8 | 25 | 26 | 27 | 28 |
29 | 30 |
31 | 39 | 40 |
41 | 42 |
43 | 44 |
45 | 46 |

Go talks

47 | 48 | {{with .Path}}

{{.}}

{{end}} 49 | 50 | {{with .Articles}} 51 |

Articles:

52 |
53 | {{range .}} 54 |
{{.Name}}: {{.Title}}
55 | {{end}} 56 |
57 | {{end}} 58 | 59 | {{with .Slides}} 60 |

Slide decks:

61 |
62 | {{range .}} 63 |
{{.Name}}: {{.Title}}
64 | {{end}} 65 |
66 | {{end}} 67 | 68 | {{with .Other}} 69 |

Files:

70 |
71 | {{range .}} 72 |
{{.Name}}
73 | {{end}} 74 |
75 | {{end}} 76 | 77 | {{with .Dirs}} 78 |

Sub-directories:

79 |
80 | {{range .}} 81 |
{{.Name}}
82 | {{end}} 83 |
84 | {{end}} 85 | 86 |
87 | 88 | 96 | 97 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /theme/templates/slides.tmpl: -------------------------------------------------------------------------------- 1 | {/* This is the slide template. It defines how presentations are formatted. */} 2 | 3 | {{define "root"}} 4 | 5 | 6 | 7 | {{.Title}} 8 | 9 | 12 | 13 | 14 | {{if .NotesEnabled}} 15 | 19 | 20 | {{end}} 21 | 22 | 39 | 40 | 41 | 42 | 43 |
44 | 45 |
46 |

{{.Title}}

47 | {{with .Subtitle}}

{{.}}

{{end}} 48 | {{if not .Time.IsZero}}

{{.Time.Format "2 January 2006"}}

{{end}} 49 | {{range .Authors}} 50 |
51 | {{range .TextElem}}{{elem $.Template .}}{{end}} 52 |
53 | {{end}} 54 |
55 | 56 | {{range $i, $s := .Sections}} 57 | 58 |
59 | {{if $s.Elem}} 60 |

{{$s.Title}}

61 | {{range $s.Elem}}{{elem $.Template .}}{{end}} 62 | {{else}} 63 |

{{$s.Title}}

64 | {{end}} 65 | {{pagenum $s 1}} 66 |
67 | 68 | {{end}}{{/* of Slide block */}} 69 | 70 |
71 |

Thank you

72 | {{range .Authors}} 73 |
74 | {{range .Elem}}{{elem $.Template .}}{{end}} 75 |
76 | {{end}} 77 |
78 | 79 |
80 | 81 |
82 | Use the left and right arrow keys or click the left and right 83 | edges of the page to navigate between slides.
84 | (Press 'H' or navigate to hide this message.) 85 |
86 | 87 | {{if .PlayEnabled}} 88 | 89 | {{end}} 90 | 91 | 101 | 102 | 103 | {{end}} 104 | 105 | {{define "newline"}} 106 |
107 | {{end}} 108 | --------------------------------------------------------------------------------