Go's Type System in One Sitting: Strings, Slices, Maps, and Implicit Interfaces
Internal Skills (Xiao Wu Xiang Gong)
Go variable standard complete declaration format:
var variableName dataType = initialValue
package main
import "fmt"
func main() {
//keyword variableName type = value
var name string = "小满"
fmt.Println(name)
}
The above is the rule for variable declaration. We declared a string-type variable name and assigned it the value "小满". When should you use a string? Most of the text and words you see on a webpage are strings, for example: "Hello, World!", "こんにちは、世界!", etc. So, when you need to store text, words, or any sequence of characters, you can use the string type.
Type Inference
Type inference is a feature of the Go language that can automatically infer the type of a variable based on its value. For example:
package main
import "fmt"
func main() {
//keyword variableName type = value
var name = "小满"
var age = 18 //int represents an integer type
fmt.Println(name, age) //Output: 小满 18
}
When you hover your mouse over the variable name, the variable's type and value are automatically displayed. As shown above, the type of name is string, and the type of age is int.
Automatic Zero Value
package main
import "fmt"
func main() {
var name string
var age int
fmt.Println(name, age) //Output: "" 0
}
We can declare a variable without assigning a value, and the variable will have a default value.
The output result is: "" 0, because name and age were not assigned values, so their default values are an empty string and 0.
Variable Shorthand
package main
import "fmt"
func main() {
//variableName := value
name := "小满"
fmt.Println(name)
}
We can use := to shorthand variable declaration, which can omit the type and keyword, but cannot omit the variable name and value.
Note: Variable shorthand can only be used inside functions, not for global variables.
Multiple Variable Declaration
package main
import "fmt"
func main() {
//Multiple variables are separated by commas
age, name := 18, "小满"
fmt.Println(age, name) //Output: 18 小满
}
Multiple variable declarations need to be separated by ,, and the assignment is also done in order. For example, age = 18, name = "小满".
Assignment
- Declare a variable of type string with the value "小满".
- Declare a variable of type integer with the value 18.
- Use multiple variable declaration and shorthand methods, and output to the terminal.
Core Internal Skills (Chun Yang Wu Ji Gong)
String
package main
import "fmt"
func main() {
text := "这是一段文本,苍天已死,黄天当立,岁在甲子,天下大吉。"
text += "\n这是第二段文本,天地玄黄,宇宙洪荒,日月盈昃,辰宿列张。"
fmt.Println(text)
}
In Go, strings need to be wrapped in double quotes. If you have multiple pieces of text to concatenate, you can use the plus sign + for concatenation. If you need a newline, you can use the backslash \n for a line break.
The output content is as follows:
这是一段文本,苍天已死,黄天当立,岁在甲子,天下大吉。
这是第二段文本,天地玄黄,宇宙洪荒,日月盈昃,辰宿列张。
Numbers
package main
import "fmt"
func main() {
var age int = 18
fmt.Println(age)
}
Go has multiple numeric types, including integers, floating-point numbers, and complex numbers.
Integers include both signed and unsigned types. Signed types include int8, int16, int32, int64, and unsigned types include uint8, uint16, uint32, uint64.
The difference between signed and unsigned is: signed can represent positive and negative numbers, while unsigned can only represent positive numbers.
| Type | Bytes Occupied | Value Range |
|---|---|---|
| int8 | 1 byte | -128 ~ 127 |
| int16 | 2 bytes | -32768 ~ 32767 |
| int32 | 4 bytes | -2147483648 ~ 2147483647 |
| int64 | 8 bytes | -9223372036854775808 ~ 9223372036854775807 |
| int | Adaptive | Same as int32 on 32-bit, int64 on 64-bit |
| Type | Bytes Occupied | Value Range |
|---|---|---|
| uint8 | 1 byte | 0 ~ 255 |
| uint16 | 2 bytes | 0 ~ 65535 |
| uint32 | 4 bytes | 0 ~ 4294967295 |
| uint64 | 8 bytes | 0 ~ 18446744073709551615 |
| uint | Adaptive | Same as uint32 on 32-bit, uint64 on 64-bit |
| uintptr | Adaptive | Same range as uint, used for storing memory addresses |
Floating-point numbers include single-precision and double-precision, corresponding to float32 and float64.
| Type | Name | Bytes | Effective Precision |
|---|---|---|---|
| float32 | Single-precision | 4 | 5~7 digits |
| float64 | Double-precision | 8 | 15~16 digits |
Boolean
package main
import "fmt"
func main() {
var isShow bool = true
fmt.Println(isShow)
}
Boolean values have only two states, true and false. They are generally used for conditional judgments and status representation.
For example: a switch, if it is on it is (true), if it is off it is (false).
Array and Slice
package main
import "fmt"
func main() {
//Array
var arr [5]int // Define an integer array of length 5, but unassigned, so output is [0 0 0 0 0]
fmt.Println(arr)
//----------------------------------------------------------------------
arr2 := [5]int{1, 2, 3, 4, 5} // Define an integer array of length 5 and assign values [1 2 3 4 5]
fmt.Println(arr2)
//----------------------------------------------------------------------
//Slice
arr3 := []int{} // Define an empty slice
arr3 = append(arr3, 6, 6, 6, 6, 6, 6, 6) // Append elements
fmt.Println(arr3) // Output is [6 6 6 6 6 6 6]
fmt.Println(len(arr3)) // Get the length of the slice, output is 7
}
Array is a contiguous block of memory with a fixed length. Once defined, the length cannot be changed. Unassigned elements will use the zero value of the corresponding type (0 for integers).
Slice is an abstraction over an array, with a variable length, but it still relies on an underlying array. Commonly use append to add elements, len to get the current length, and cap to get the capacity of the underlying array.
| Feature | Array | Slice |
|---|---|---|
| Length | Fixed, determined at definition | Variable |
| Declaration | [5]int |
[]int |
| Passing Args | Pass by value, copies the whole array | Pass by reference, shares underlying data |
| Use Case | Fixed size, performance-sensitive | Most common in daily development |
Map
package main
import "fmt"
func main() {
// Define a map with string keys and int values
scores := map[string]int{
"张三": 90,
"李四": 85,
"王五": 92,
}
fmt.Println(scores["张三"]) // Output: 90
// Add or modify key-value pairs
scores["赵六"] = 88
delete(scores, "李四") // Delete a key-value pair
// Check if a key exists
score, ok := scores["张三"]
if ok {
fmt.Println("张三的分数是", score)
}
}
A map (map) is a collection of key-value pairs, allowing quick lookup of a value by its key. The key type must be a comparable type (like string, int), and the value can be any type.
Common operations:
map[key]— Reads the value; returns the zero value if the key does not existmap[key] = value— Adds or modifiesdelete(map, key)— Deletes a key-value pairvalue, ok := map[key]— Checks if a key exists;okistrueif it exists
Struct
package main
import "fmt"
// Define a struct type
type Person struct {
Name string
Age int
}
func main() {
// Create a struct instance
p := Person{
Name: "小满",
Age: 18,
}
fmt.Println(p.Name, p.Age) // Output: 小满 18
// Access and modify fields
p.Age = 20
fmt.Println(p.Age) // Output: 20
}
A struct (struct) is used to combine multiple fields of different types into a custom type, forming the basis of object-oriented programming. It is defined using type Name struct { ... }, and fields are accessed with the dot . operator.
Structs are suitable for describing entities with multiple attributes, such as user information, product details, coordinate points, etc.
Interface
package main
import "fmt"
// Define an interface: contains a Speak method
type Animal interface {
Speak() string
}
type Dog struct{}
type Cat struct{}
func (d Dog) Speak() string { return "汪汪" }
func (c Cat) Speak() string { return "喵喵" }
func main() {
var a Animal
a = Dog{}
fmt.Println(a.Speak()) // Output: 汪汪
a = Cat{}
fmt.Println(a.Speak()) // Output: 喵喵
}
An interface (interface) defines a set of method signatures. Any type that implements these methods automatically satisfies the interface without explicit declaration. This is Go's core mechanism for achieving polymorphism.
Interface characteristics:
- Implicit Implementation: As long as a type implements all methods of an interface, it satisfies that interface.
- Empty Interface
interface{}(orany) can accept values of any type. - Composed Interfaces: Multiple interfaces can be embedded and combined into a larger interface.
Interfaces make code more flexible—functions can accept interface type parameters, thus being compatible with all types that implement the interface, making extension and testing easier.
Assignment
- String: Declare two string variables, storing your name and school name respectively. Concatenate them using
+and print, separating them with a newline character\n. - Numbers: Declare an
inttype variable for age and afloat64type variable for height (e.g.,175.5), and print them out. - Boolean: Declare a
boolvariable representing "is online", with an initial value oftrue. Print it, then change it tofalseand print again. - Array and Slice:
- Define an integer array of length 3, assign values
[10, 20, 30]and print it; - Define an empty slice, use
appendto sequentially add1, 2, 3, print the slice content and its lengthlen.
- Define an integer array of length 3, assign values
- Map: Create a
map[string]int, store the names and scores of 3 classmates, print one of their scores, add a new classmate and delete one of them, and finally iterate and print all key-value pairs. - Struct: Define a
Bookstruct containingTitle(book title) andPrice(price) fields, create an instance of a book, and print its title and price. - Interface: Define a
Shapeinterface containing anArea() float64method; then define aRectangle(rectangle) struct and implement this interface, create an instance, and print its area. - Comprehensive Exercise: Put the above
Bookstructs into a slice, store at least 3 books, iterate over the slice, and print the information for each book.
Top 2 of 3 from juejin.cn, machine-translated. The original thread is authoritative.
Go's automatic inheritance problem, I feel it's really not good [smile]
Doesn't Go not have inheritance?
My god, even the big shots are starting to learn Go