Golang
时间轴
2025-10-14
init
Basics
1.Package
- Every Go program is made up of packages
- program start with package main
By convention, the package name is the same as the last element of the import path.
For instance, the “math/rand“ package comprises files that begin with the statement package rand.
2.Imports
1 | import ( |
3.Exported names
A name is exported if it begin with a capital letter.
1 | package main |
4.Functions
Notice that the type comes after the variable name.
1 | package main |
Syntactic Sugar
When two or more consecutive named function parameters share a type, you can omit the type from all but the last.
1 | func add(x, y int) int { |
Multiple results
A function can return any number of results
1 | package main |
Named return values
Go’s return values may be named.
If so, they are treated as variables defined at the top of the function.
A return statement without arguments returns the named return values. This is known as a “naked” return.
1 | package main |
Suggestions: Naked return statements should be used only in short functions, as with the example shown here. They can harm readability in longer functions.
5.Variables
- The var statement declares a list of variables;
- as in function argument lists, the type is last.
1 | package main |
Initializer
A var declaration can include initializers, one per variable.
If an initializer is present, the type can be omitted; the variable will take the type of the initializer.
1 | package main |
Variables declared without an explicit initial value are given their *zero value***.**
The zero value is:
- 0 for numeric types,
- false for the boolean type, and
- “” (the empty string) for strings.
1 | package main |
Short variable declarations
- Inside a function, the “ := “ short assignment statement can be used in place of a var declaration with implicit type.
- Outside a function, every statement begins with a keyword (var, func, and so on) and so the := construct is not available.
1 | package main |
6.Basic Types
1 | bool |
- The int, uint, and uintptr types are usually 32 bits wide on 32-bit systems and 64 bits wide on 64-bit systems.
- When you need an integer value you should use int unless you have a specific reason to use a sized or unsigned integer type.
example
1 | package main |
Type conversions
The expression T(v) converts the value v to the type T.
1 | package main |
Unlike in C, in Go assignment between items of different type requires an explicit conversion
Type Inference
1 | var i int |
7.Constants
- Constants are declared like variables, but with the const keyword.
- Constants can be character, string, boolean, or numeric values.
- Constants cannot be declared using the := syntax.
1 | package main |
Numeric Constants
- Numeric constants are high-precision values.
An untyped constant takes the type needed by its context.
1 | import "fmt" |
8.For
Go has only one looping construct, the for loop.
The basic for loop has three components separated by semicolons:
- the init statement: executed before the first iteration
- the condition expression: evaluated before every iteration
- the post statement: executed at the end of every iteration
1 | package main |
but the init and post statements are optional.
1 | package main |
For is Go’s “while”
1 | package main |
Forever
1 | package main |
9.If
Go’s if statements are like its for loops; the expression need not be surrounded by parentheses ( ) but the braces { } are required.
1 | package main |
If with a short statement
- Like for, the if statement can start with a short statement to execute before the condition.
- Variables declared by the statement are only in scope until the end of the if.
1 | package main |
Variables declared inside an if short statement are also available inside any of the else blocks.
10.Switch
Go’s switch is like the one in C, C++, Java, JavaScript, and PHP, except that Go only runs the selected case, not all the cases that follow.
1 | package main |
Switch cases evaluate cases from top to bottom, stopping when a case succeeds.
- Switch without a condition is the same as switch true.
This construct can be a clean way to write long if-then-else chains.
1 | package main |
11.Defer
- A defer statement defers the execution of a function until the surrounding function returns.
- The deferred call’s arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.
1 | package main |
Deferred function calls are pushed onto a stack. When a function returns, its deferred calls are executed in last-in-first-out order.
1 | package main |
12.Pointers
A pointer holds the memory address of a value
The type *T is a pointer to a T value. Its zero value is nil.
1 | var p *int |
- Unlike C, Go has no pinter arithmetic
13.Struct
A struct is a collection of fields
1 | package main |
- the struct fields are accessed using a dot.
- the struct fields can be accessed by a pointer through a struct pointer.Like Rust,you can use p.x instead of (*p).x , without the explicit dereference
struct literals
a struct literal denotes a newly allocated struct value by listing the values of its fields.
1 | package main |
14.Array
The type [n]T is an array of n values of type T
1 | package main |
- An array’s length is part of its type, so arrays cannot be resized.
15.Slices
like rust
A slice is formed by specifying two indices a low and high bound,separated by a colon,
1 | a[low:high] |
- this selects a half-open range which includes the first element,but excludes the last one
1 | package main |
- a slice does not store any data,it just describes a section of an underlying array
- Changing the elements of a slice modifies the corresponding elements of its underlying array.
slice literals:
A slice literal is like an array literal without the length
1 | package main |
like rust,the slice has defaults
these slice expressions are equivalent:
1 | a[0:10] |
length and capacity
A slice has both a length and a capacity.
- The length of a slice is the number of elements it contains.
- The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice.
- The length and capacity of a slice s can be obtained using the expressions len(s) and cap(s).
- You can extend a slice’s length by re-slicing it, provided it has sufficient capacity.
1 | package main |
Nil slices
The zero value of a slice is nil
A nil slice has a length and capacity of 0 and has no underlying array.
1 | package main |
Creating a slice with make
Slices can be created with the built-in make function; this is how you create dynamically-sized arrays.
- The make function allocates a zeroed array and returns a slice that refers to that array:
1 | a := make([]int, 5) // len(a)=5 |
- To specify a capacity, pass a third argument to make:
1 | b := make([]int, 0, 5) // len(b)=0, cap(b)=5 |
slices of slices
slices can contain any type,including other slices
1 | package main |
Appending to a slice
1 | func append(s []T, vs ...T) []T |
The first parameter s of append is a slice of type T, and the rest are T values to append to the slice.
1 | package main |
16.Range
the range form of the for loop iterates over a slice or map
like rust,When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.
1 | package main |
You can skip the index or value by assigning to _.
1 | for i, _ := range pow for _, value := range pow |
If you only want the index, you can omit the second variable.
1 | for i := range pow |
17.Map
A map maps keys to values.
The zero value of a map is nil. A nil map has no keys, nor can keys be added.
The make function returns a map of the given type, initialized and ready for use.
1 | package main |
Map literals
Map literals are like struct literals, but the keys are required.
1 | package main |
Mutating Maps
insert or update an element in map m:
1 | m[key] = elem |
retrieve an element
1 | elem = m[key] |
delete an element
1 | delete(m,key) |
test that a key is present with a two-value assignment
1 | elemt,ok = m[key] |
- If key is in m, ok is true. If not, ok is false.
- If key is not in the map, then elem is the zero value for the map’s element type.
18.Function values
Functions are values too. They can be passed around just like other values.
Function values may be used as function arguments and return values.
1 | package main |
19.Function closures
Go functions may be closures.
A closure is a function value that references variables from outside its body.
The function may access and assign to the referenced variables
1 | package main |
Methods and interfaces
1.Methods
Go does not have classes. However, you can define methods on types.
A method is a function with a special receiver argument.
The receiver appears in its own argument list between the func keyword and the method name.
1 | package main |
Remember: a method is just a function with a receiver argument.
Here’s Abs written as a regular function with no change in functionality.
1 | package main |
You can declare a method on non-struct types, too.
1 | package main |
Pointer receivers
1 | package main |
Methods with pointer receivers can modify the value to which the receiver points (as Scale does here). Since methods often need to modify their receiver, pointer receivers are more common than value receivers.
It can avoid copying the value on each method call. This can be more efficient if the receiver is a large struct, for example.
With a value receiver, the Scale method operates on a copy of the original Vertex value. (This is the same behavior as for any other function argument.) The Scale method must have a pointer receiver to change the Vertex value declared in the main function.
2.Interfaces
1 | package main |
An interface type is defined as a set of method signatures.
A value of interface type can hold any value that implements those methods.
A type implements an interface by implementing its methods. There is no explicit declaration of intent, no “implements” keyword.
Under the hood, interface values can be thought of as a tuple of a value and a concrete type:
(value, type)
1 | package main |
If the concrete value inside the interface itself is nil, the method will be called with a nil receiver.
1 | package main |
In some languages this would trigger a null pointer exception, but in Go it is common to write methods that gracefully handle being called with a nil receiver (as with the method M in this example.)
A nil interface value holds neither value nor concrete type.Calling a method on a nil interface is a run-time error because there is no type inside the interface tuple to indicate which concrete method to call.
Empty Interface:
The interface type that specifies zero methods is known as the empty interface:
interface{}
An empty interface may hold values of any type. (Every type implements at least zero methods.)
1 | package main |
Empty interfaces are used by code that handles values of unknown type. For example, fmt.Print takes any number of arguments of type interface{}.
Type assertions
1 | package main |
Type switches
1 | package main |
A type switch is like a regular switch statement, but the cases in a type switch specify types (not values), and those values are compared against the type of the value held by the given interface value.
Stringers
1 | package main |
One of the most ubiquitous interfaces is Stringer defined by the fmt package.
type Stringer interface { String() string }
A Stringer is a type that can describe itself as a string. The fmt package (and many others) look for this interface to print values.
3.Errors
Go programs express error state with error values.
The error type is a built-in interface similar to fmt.Stringer:
1 | type error interface { |
(As with fmt.Stringer, the fmt package looks for the error interface when printing values.)
Functions often return an error value, and calling code should handle errors by testing whether the error equals nil.
1 | i, err := strconv.Atoi("42") |
A nil error denotes success; a non-nil error denotes failure.
1 | package main |
4.Readers
The io package specifies the io.Reader interface, which represents the read end of a stream of data.
The Go standard library contains many implementations&ss=go%2Fgo>) of this interface, including files, network connections, compressors, ciphers, and others.
The io.Reader interface has a Read method:
1 | func (T) Read(b []byte) (n int, err error) |
Read populates the given byte slice with data and returns the number of bytes populated and an error value. It returns an io.EOF error when the stream ends.
The example code creates a strings.Reader and consumes its output 8 bytes at a time.
1 | package main |
Generics
1.Type parameter
Go functions can be written to work on multiple types using type parameters. The type parameters of a function appear between brackets, before the function’s arguments.
1 | package main |
This declaration means that s is a slice of any type T that fulfills the built-in constraint comparable. x is also a value of the same type.
comparable is a useful constraint that makes it possible to use the == and != operators on values of the type. In this example, we use it to compare a value to all slice elements until a match is found. This Index function works for any type that supports comparison.
3.Generic types
1 | package main |
Go also supports generic types. A type can be parameterized with a type parameter, which could be useful for implementing generic data structures.
Concurrency
1.Goroutines
A goroutine is a lightweight thread managed by the Go runtime.
1 | package main |
2.Channels
Channels are a typed conduit through which you can send and receive values with the channel operator, <-.
1 | ch <- v // Send v to channel ch. |
By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables.
1 | package main |
3.Buffered Channels
Channels can be buffered. Provide the buffer length as the second argument to make to initialize a buffered channel:
1 | package main |
Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.
4.Range and Close
A sender can close a channel to indicate that no more values will be sent. Receivers can test whether a channel has been closed by assigning a second parameter to the receive expression: after
1 | v, ok := <-ch |
ok is false if there are no more values to receive and the channel is closed.
1 | package main |
Note: Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic.
Another note: Channels aren’t like files; you don’t usually need to close them. Closing is only necessary when the receiver must be told there are no more values coming, such as to terminate a range loop.
5.Select
The select statement lets a goroutine wait on multiple communication operations.
A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.
1 | package main |
while,The default case in a select is run if no other case is ready.
1 | package main |
6.sync.Mutex
We’ve seen how channels are great for communication among goroutines.
But what if we don’t need communication? What if we just want to make sure only one goroutine can access a variable at a time to avoid conflicts?
This concept is called mutual exclusion, and the conventional name for the data structure that provides it is mutex.
Go’s standard library provides mutual exclusion with sync.Mutex and its two methods:
- Lock
- Unlock
We can define a block of code to be executed in mutual exclusion by surrounding it with a call to Lock and Unlock as shown on the Inc method.
We can also use defer to ensure the mutex will be unlocked as in the Value method
1 | package main |