Golang datatypes: Difference between revisions
(→String) |
(→Slices) |
||
Line 201: | Line 201: | ||
len(numbers) == 3 // length | len(numbers) == 3 // length | ||
cap(numbers) == 3 // capacity | cap(numbers) == 3 // capacity | ||
// append to slice, growing array if necessary | // append to slice, growing array if necessary | ||
Line 215: | Line 209: | ||
otherSlice = []int{6, 7, 8} | otherSlice = []int{6, 7, 8} | ||
append(numbers, ...otherSlice) | append(numbers, ...otherSlice) | ||
</syntaxhighlight> | |||
One interesting property of append, is that it assumes you want to grow the underlying array.<br> | |||
This makes it convenient to start with length 0, and grow your array as needed.<br> | |||
Unfortunately this is very costly, setting the capacity pre-allocates an array you can just add items to. | |||
<syntaxhighlight lang="go"> | |||
// Yuck -- each append creates a new (len+1) array, and copies old array into it | |||
numbers = make(int[], 0) // length=0, capacity=0 | |||
append(numbers, 1) | |||
append(numbers, 2) | |||
// Nice - we won't need to resize array until we add the 6th item | |||
numbers = make(int[], 0, 5) | |||
append(numbers, 1) | |||
append(numbers, 2) | |||
// Nicer - once we hit the 6th item, let's grow in increments of the capacity | |||
numbers := make([]int, 0, 5) | |||
numbers = append(numbers, 1, 2, 3, 4, 5) | |||
buf := make([]int, len(numbers), cap(numbers) * 2) | |||
copy(buf, numbers) | |||
numbers = buf | |||
fmt.Println(numbers) // [1 2 3 4 5] | |||
fmt.Println(cap(numbers)) // 10 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Slices --> | </blockquote><!-- Slices --> |
Revision as of 21:32, 29 May 2022
Literal Types
"foo" // string 123 // int (cpu-arch dependent bitsize) 3.14 // float64 6.2e25 // float64 true, false // bool
Boolean
var condition bool = true
Text
String
Go's strings are bytestrings by default.
The are treated as arrays of bytes.
- Strings are immutable.
- Strings are UTF-8
TODO:
write some best pratices for handling multi-byte characters
var name string = "will" // string name := "will" // string // slices var ascii_code uint8 = name[1] // 2nd char from string var char string = string(ascii_code) // get string from UTF-8 codepoint number bytestring := []byte("hi") == [104, 105] // string as bytes (uint8) // operators msg := "hello " + "world" // concatenationRune
Runes are UTF-32 strings.
(Each character is auint32
)
Numeric
Integers
Integer sizes are expressed by their bit-size.
signed
int // (however many bits your CPU word-size is) int8 // 128 - 127 int16 // 32,768 - 32,767 int32 // 2,147,483,648 - 2,147,483,647 int64 // 9,223,372,036,854,775,808 - 9,223,372,036,854,775,807unsigned
uint // (however many bits your CPU word-size is) uint8 // 0 - 255 uint16 // 0 - 65,535 uint32 // 0 - 4,294,967,295 // uint64 does not existBytes
Same as
uint8
.math/big
Slow, but handles numbers of any size.
Complex Numbers
Go lets you represent complex/imaginary numbers.
var num complex64 = 1 + 2i var num complex128 = 1 + 2i var num complex64 = 2i // alternative for 1 + 2i var num complex64 = complex(1, 2) // alternative for 1 + 2iYou can also extract the complex/imaginary part of the number.
var num complex64 = 1 + 2i real(num) // the real number component imag(num) // the imaginary number component
Pointers
uintptr // a pointer of however many bits your CPU word-size is
Collections
Arrays
Arrays are statically-sized, homogenous collections of items,
stored contiguously in memory.family := [2]string{"will", "alex"} // create 2-item array with these elements family := [...]string{"will", "alex"} // create array whose size matches provided elements var family [2]string // create 2-item array, then assign elements family[0] = "will" family[1] = "alex" var families string[3][2] // create an empty nested array families := [...]string{ // create nested array using literals [...]string{"will", "alex"}, [...]string{"tom", "fiona"}, [...]string{"alex", "morgan"}, } len(family) == 2While arrays are mutable, when assigning an array to a new variable,
you're actually duplicating the array.numbers := [...]int{1, 2, 3} copy_of_numbers := numbers copy_of_numbers[1] = 9 // <-- does not change 'numbers' fmt.Println(numbers) // [1 2 3] fmt.Println(copy_of_numbers) // [1 9 3]Rather than passing array-data to a function, in most cases, you probably want to pass a pointer to it.
numbers := [...]int{1, 2, 3} ref_to_numbers := &numbers // <-- get pointer to 'numbers' ref_to_numbers[1] = 9 fmt.Println(numbers) // [1 9 3] fmt.Println(ref_to_numbers) // &[1 9 3]Slices
The Slice datastructure is a resizable abstraction built overtop of an array.
see https://go.dev/blog/slices-introA slice's datastructure is composed of:
- pointer to array element
- length of slice
- capacity (length) of underlying array
Some properties:
- Assigning a slice to another variable will not duplicate the data
- Changing a slice will change the underlying array
- Resizing a slice is fairly cheap. Methods exist to duplicate array into a larger one when required.
building slicesnumbers := []int{1, 2, 3} // build an empty slice numbers = make([]int, 3, 3) // `make(type, length, [capacity])` numbers = make([]int, 3) // if not specified, capacity matches lenth // build slices from arrays, or other slices numbers := [...]{1, 2, 3, 4, 5} // array {1, 2, 3, 4, 5} mySlice := numbers[:2] // slice {1, 2, 3}slice functions
len(numbers) == 3 // length cap(numbers) == 3 // capacity // append to slice, growing array if necessary numbers := []int{1, 2, 3} append(numbers, 4, 5) // extend/concatenate slices otherSlice = []int{6, 7, 8} append(numbers, ...otherSlice)One interesting property of append, is that it assumes you want to grow the underlying array.
This makes it convenient to start with length 0, and grow your array as needed.
Unfortunately this is very costly, setting the capacity pre-allocates an array you can just add items to.// Yuck -- each append creates a new (len+1) array, and copies old array into it numbers = make(int[], 0) // length=0, capacity=0 append(numbers, 1) append(numbers, 2) // Nice - we won't need to resize array until we add the 6th item numbers = make(int[], 0, 5) append(numbers, 1) append(numbers, 2) // Nicer - once we hit the 6th item, let's grow in increments of the capacity numbers := make([]int, 0, 5) numbers = append(numbers, 1, 2, 3, 4, 5) buf := make([]int, len(numbers), cap(numbers) * 2) copy(buf, numbers) numbers = buf fmt.Println(numbers) // [1 2 3 4 5] fmt.Println(cap(numbers)) // 10