首页/文章/Golang

golang文档

2026-04-10
642122 分钟
...

1. Go 是什么

Go 是一种强类型、垃圾回收、原生支持并发的编程语言。代码由 package 组成;用 module 管理依赖;可执行程序通常从 package main 的 main() 函数开始运行。Go 官方一直强调兼容性,Go 1.26 也继续保持 Go 1 的兼容承诺。

最小可运行程序:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

这里你已经看到了 Go 最核心的 3 个语法点:

package 声明包、import 导入包、func 声明函数。main 包里的 main() 是程序入口。

2. 先记住 Go 的代码长什么样

一个典型 Go 文件:

package main

import (
    "fmt"
    "time"
)

const AppName = "demo"

var globalCount int = 0

type User struct {
    Name string
    Age  int
}

func (u User) SayHi() {
    fmt.Println("Hi,", u.Name)
}

func main() {
    u := User{Name: "Hua", Age: 18}
    u.SayHi()
    fmt.Println(AppName, time.Now())
}

这已经包含了很多 Go 语法:

常量、变量、结构体、方法、短变量声明、包导入。Go 倾向于代码结构清晰而不是语法花哨。

3. 关键字与标识符

Go 有一组保留关键字,例如:

break      default    func       interface  select
case       defer      go         map        struct
chan       else       goto       package    switch
const      fallthrough if        range      type
continue   for        import     return     var

这些不能拿来当变量名、函数名、类型名。标识符命名时,首字母大写表示可导出(public),小写表示包内私有。比如 User 可被别的包访问,user 不行。

例子:

package demo

var PublicName = "可以被外部包访问"
var privateName = "只能在当前包内访问"

4. 注释

Go 支持两种注释:

// 单行注释

/*
多行注释
*/

日常开发里最常用的是 //。放在顶层声明前的注释还会被当作文档注释。

5. 变量:var**:=**

5.1 基本声明

var name string
var age int
var isAdmin bool

Go 有零值概念:

string 默认是 “”,int 默认是 0,bool 默认是 false,指针 / slice / map / chan / func / interface 默认是 nil。

5.2 声明并初始化

var name string = "Hua"
var age = 18

如果右边有值,很多时候可以省类型,让编译器推断。

5.3 短变量声明**:=**

name := "Hua"
age := 18

这是 Go 里最常用的写法,但只能在函数内部使用,不能用于包级变量。

5.4 多变量声明

var a, b int = 1, 2
x, y := "hello", true

5.5 分组声明

var (
    name string = "Hua"
    age  int    = 18
)

**6. 常量:**const

常量在编译期确定,常用来放固定配置、枚举值。

const Pi = 3.14
const AppName = "myapp"

也支持分组:

const (
    StatusPending = 0
    StatusDone    = 1
    StatusFail    = 2
)

7.iota:Go 里的枚举神器

Go 没有传统语言那种 enum 关键字,通常用 const + iota 实现枚举。

const (
    Red = iota
    Green
    Blue
)

值依次是 0 1 2。

更常见的业务写法:

type Status int

const (
    StatusPending Status = iota
    StatusPaid
    StatusShipped
    StatusDone
)

作用:

让状态值有明确类型,不是到处乱飞的裸数字。

8. 基本数据类型

Go 常见内建类型包括:

布尔、整数、浮点、复数、字符串。数值类型还有不同位宽版本。规范定义了这些预声明类型与常量表达式、类型推断规则。

8.1 布尔

var ok bool = true

8.2 整数

var a int = 10
var b int8 = 127
var c uint = 20
var d byte = 255   // byte 是 uint8 的别名
var e rune = '中'  // rune 是 int32 的别名,常表示 Unicode 码点

8.3 浮点

var f1 float32 = 3.14
var f2 float64 = 3.1415926

8.4 复数

var c1 complex64 = 1 + 2i
var c2 complex128 = 3 + 4i

8.5 字符串

var s string = "hello"

字符串是只读字节序列。中文按 UTF-8 存储,一个汉字可能占多个字节,所以“按下标取字符串”很容易踩坑。

例子:

s := "你好"
fmt.Println(len(s))       // 字节长度,不是字符个数
fmt.Println([]rune(s))    // 转成 rune 切片再按字符处理

9. 类型转换

Go 不做很多隐式转换,你要手动转:

var a int = 10
var b int64 = int64(a)

var f float64 = 3.14
var n int = int(f) // 小数部分会被截断

这个设计是为了让类型更明确,减少隐式转换带来的 bug。

10. 运算符

10.1 算术运算

a + b
a - b
a * b
a / b
a % b

10.2 比较运算

a == b
a != b
a > b
a < b
a >= b
a <= b

10.3 逻辑运算

a && b
a || b
!a

10.4 位运算

a & b
a | b
a ^ b
a &^ b
a << 1
a >> 1

&^ 是 Go 比较有特色的“按位清除”。

10.5 自增自减

i++
i--

注意:Go 的 ++、-- 是语句,不是表达式,不能写成:

// 错误示例
x = i++

11. 流程控制

Go 主要流程控制就 3 个:if、for、switch。Go 没有 while,但 for 可以胜任。控制语句语法里不需要圆括号

11.1 if

if age >= 18 {
    fmt.Println("成年")
} else {
    fmt.Println("未成年")
}

带初始化语句的****if

if score := 90; score >= 60 {
    fmt.Println("及格")
}

这个变量只在 if / else 作用域内有效。

11.2****for

普通 for

for i := 0; i < 5; i++ {
    fmt.Println(i)
}

类 while

sum := 0
for sum < 100 {
    sum += 10
}

无限循环

for {
    // do something
}

range

nums := []int{10, 20, 30}
for index, value := range nums {
    fmt.Println(index, value)
}

也可以只取一个:

for _, value := range nums {
    fmt.Println(value)
}

_ 是空白标识符,表示“这个值我不要”。

11.3 switch

day := 2

switch day {
case 1:
    fmt.Println("Mon")
case 2:
    fmt.Println("Tue")
default:
    fmt.Println("Other")
}

Go 的 switch 默认不会自动向下贯穿。如果你真要继续执行下一个 case,用 fallthrough。

switch n := 1; n {
case 1:
    fmt.Println("one")
    fallthrough
case 2:
    fmt.Println("two")
}

无表达式

switch

score := 85

switch {
case score >= 90:
    fmt.Println("A")
case score >= 80:
    fmt.Println("B")
default:
    fmt.Println("C")
}

很适合写区间判断。

**11.4breakcontinue、**goto

for i := 0; i < 10; i++ {
    if i == 3 {
        continue
    }
    if i == 8 {
        break
    }
    fmt.Println(i)
}

goto 也存在,但正常业务开发很少用。

12. 函数****func

函数是 Go 最核心的组织单位之一。Go 支持多返回值,这是它很重要的特性。

12.1 最基础函数

func add(a int, b int) int {
    return a + b
}

相邻参数类型相同时可简写:

func add(a, b int) int {
    return a + b
}

12.2 多返回值

func divide(a, b int) (int, int) {
    return a / b, a % b
}

调用:

q, r := divide(10, 3)
fmt.Println(q, r)

12.3 命名返回值

func calc(a, b int) (sum int, diff int) {
    sum = a + b
    diff = a - b
    return
}

能用,但别滥用。业务里普通 return x, y 通常更清晰。

12.4 可变参数

func sum(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}

调用:

fmt.Println(sum(1, 2, 3))

切片展开:

arr := []int{1, 2, 3}
fmt.Println(sum(arr...))

12.5 函数也是值

func apply(a, b int, fn func(int, int) int) int {
    return fn(a, b)
}

12.6 匿名函数

fn := func(name string) {
    fmt.Println("hello", name)
}
fn("Hua")

12.7 闭包

func counter() func() int {
    n := 0
    return func() int {
        n++
        return n
    }
}

作用:

让内部函数记住外层变量,常用于状态封装、回调、工厂函数。

**13.**defer

defer 表示“当前函数快结束时再执行”。最常用于释放资源:关闭文件、解锁、关闭连接。

func readFile() {
    f, err := os.Open("a.txt")
    if err != nil {
        return
    }
    defer f.Close()

    // 使用 f
}

多个 defer 按后进先出执行。

func test() {
    defer fmt.Println(1)
    defer fmt.Println(2)
    defer fmt.Println(3)
}
// 输出顺序:3 2 1

**14. 错误处理:**error

Go 不用异常做日常错误处理,而是显式返回 error。这是 Go 开发的基本功。

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("除数不能为 0")
    }
    return a / b, nil
}

调用:

result, err := divide(10, 0)
if err != nil {
    fmt.Println("出错:", err)
    return
}
fmt.Println(result)

14.1 自定义错误

type MyError struct {
    Msg string
}

func (e MyError) Error() string {
    return e.Msg
}

只要实现了 Error() string,就满足 error 接口。

15.panic与****recover

panic 表示程序出现了严重错误,开始向上层栈展开;recover 只能在 defer 中捕获 panic。它们适合处理“不应该发生”的情况,不适合作为普通业务错误机制。

func test() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("捕获到 panic:", r)
        }
    }()

    panic("出大问题了")
}

16. 指针

Go 有指针,但没有指针运算。指针用于修改原值、避免大对象复制。

func inc(n *int) {
    *n++
}

func main() {
    x := 10
    inc(&x)
    fmt.Println(x) // 11
}

记法:

  • *T:指向 T 的指针类型

  • &x:取地址

  • *p:解引用

17. 数组****array

数组长度是类型的一部分。

var a [3]int
a[0] = 10
fmt.Println(a)

直接初始化:

b := [3]int{1, 2, 3}

自动推长度:

c := [...]int{1, 2, 3, 4}

Go 里数组用得没有切片多,因为数组长度固定,传参还会复制整个数组。

18. 切片****slice

切片是 Go 里最常用的数据结构之一。它是对底层数组的一层视图,带长度和容量。

18.1 声明

var s []int

零值是 nil。

18.2 初始化

s := []int{1, 2, 3}

18.3****make

s := make([]int, 3)      // len=3 cap=3
s2 := make([]int, 3, 5)  // len=3 cap=5

18.4 截取

arr := [5]int{1, 2, 3, 4, 5}
s := arr[1:4] // [2 3 4]

规则:

  • a[start:end]

  • 包左不包右

  • 可省略一边

s[:3]
s[1:]
s[:]

18.5****append

s := []int{1, 2}
s = append(s, 3)
s = append(s, 4, 5)

注意:append 可能返回新底层数组,所以要接住返回值。

18.6****copy

src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)

18.7 常见坑:共享底层数组

a := []int{1, 2, 3, 4}
b := a[:2]
b[0] = 100
fmt.Println(a) // [100 2 3 4]

因为 b 和 a 可能指向同一底层数组。

**19.**map

map 是键值对结构。零值是 nil;nil map 可以读,不能写。通常用 make 初始化。

19.1 声明与初始化

var m map[string]int
m = make(map[string]int)

m["age"] = 18

字面量:

m := map[string]int{
    "age":  18,
    "score": 99,
}

19.2 取值

fmt.Println(m["age"])

如果 key 不存在,会返回 value 类型的零值。

19.3 判断 key 是否存在

v, ok := m["name"]
if ok {
    fmt.Println("存在:", v)
} else {
    fmt.Println("不存在")
}

19.4 删除

delete(m, "age")

19.5 遍历

for k, v := range m {
    fmt.Println(k, v)
}

注意:map 遍历顺序不保证固定

20. 结构体****struct

结构体是 Go 组合数据的核心方式。

20.1 声明

type User struct {
    Name string
    Age  int
}

20.2 初始化

u1 := User{Name: "Hua", Age: 18}
u2 := User{"Tom", 20}

更推荐第一种,字段名清晰,不怕字段顺序变化。

20.3 访问字段

fmt.Println(u1.Name)
u1.Age = 19

20.4 指向结构体的指针

u := &User{Name: "Hua", Age: 18}
fmt.Println(u.Name) // Go 自动解引用

21. 方法****method

Go 里可以给类型绑定方法。方法本质上是“带接收者的函数”。

type User struct {
    Name string
}

func (u User) SayHi() {
    fmt.Println("Hi,", u.Name)
}

调用:

u := User{Name: "Hua"}
u.SayHi()

21.1 值接收者 vs 指针接收者

值接收者

func (u User) Rename(name string) {
    u.Name = name
}

这里改的是副本,外面原值不变。

指针接收者

func (u *User) Rename(name string) {
    u.Name = name
}

这样才能修改原对象。

经验:

  • 需要修改对象:用指针接收者

  • 结构体比较大:通常也用指针接收者

  • 尽量保持同一类型的方法接收者风格一致

22. 类型type:自定义类型与别名

22.1 定义新类型

type MyInt int

这是新类型,不等于 int。

22.2 类型别名

type MyIntAlias = int

这是别名,等同于 int。

作用区别很大,别混了。

23. 接口****interface

接口是 Go 抽象能力的核心。Go 的接口是隐式实现:一个类型只要实现了接口要求的方法,就自动实现这个接口,不需要 implements。

23.1 定义接口

type Speaker interface {
    Speak() string
}

23.2 实现接口

type Dog struct{}

func (Dog) Speak() string {
    return "wang"
}

23.3 使用接口

func say(s Speaker) {
    fmt.Println(s.Speak())
}

23.4 空接口

var x interface{}
x = 10
x = "hello"

interface{} 能表示任意值。

现在更常见也更直观的写法是:

var x any

any 是 interface{} 的别名。

24. 类型断言与类型选择

当你拿到接口值,想知道底层实际类型时,用类型断言。

24.1 类型断言

var x any = "hello"

s, ok := x.(string)
if ok {
    fmt.Println(s)
}

如果你直接写:

s := x.(string)

断言失败会 panic。

24.2 type switch

func printType(v any) {
    switch t := v.(type) {
    case int:
        fmt.Println("int", t)
    case string:
        fmt.Println("string", t)
    default:
        fmt.Println("unknown")
    }
}

25. 组合与嵌入(embedding)

Go 没有传统 OOP 的继承,常用组合。结构体里可以嵌入另一个结构体或接口。

type Address struct {
    City string
}

type User struct {
    Name string
    Address
}

func main() {
    u := User{Name: "Hua", Address: Address{City: "Tokyo"}}
    fmt.Println(u.City) // 直接访问嵌入字段
}

这是一种非常 Go 风格的代码复用方式。

26. 包package与导入****import

Go 用包组织代码。一个目录通常一个包。package main 表示可执行程序包。导入语法有单行和分组两种。

import "fmt"
import (
    "fmt"
    "time"
)

26.1 别名导入

import f "fmt"

26.2 匿名导入

import _ "github.com/lib/pq"

用于只执行包的 init(),自己不直接用包名。

26.3 点导入

import . "fmt"

这样可以直接写 Println(),但一般不推荐,容易污染命名空间。

27. 模块****go.mod

现代 Go 用 module 管理依赖。新项目通常先:

go mod init example/myapp

这会生成 go.mod。模块路径通常对应仓库地址;Go 官方教程也建议这样做。

常用命令:

go mod init example/myapp
go mod tidy
go run .
go build .
go test ./...

28. 可见性规则

Go 没有 public/private 关键字,靠首字母大小写控制导出。

type user struct{}  // 包内私有
type User struct{}  // 对外可见

func do() {}        // 私有
func Do() {}        // 导出

**29. 初始化:**init()

每个包可以定义 init() 函数,在包初始化时自动执行。常用于注册、默认配置、驱动初始化。

func init() {
    fmt.Println("package init")
}

注意:

  • 不能主动调用 init()

  • 一个包可有多个 init()

  • 不要把复杂业务逻辑塞进去

30. 并发:goroutine、channel、select、go 关键字

Go 的并发是语言级特性,不只是库功能。官方 Tour 也把它作为语言核心部分。

**30.1 goroutine:**go

go func() {
    fmt.Println("异步执行")
}()

加上 go 关键字,函数就在新的 goroutine 里运行。

**30.2 channel:**chan

channel 用于 goroutine 之间通信。

ch := make(chan int)

go func() {
    ch <- 42
}()

v := <-ch
fmt.Println(v)

带缓冲 channel

ch := make(chan int, 2)
ch <- 1
ch <- 2

关闭 channel

close(ch)

遍历 channel

for v := range ch {
    fmt.Println(v)
}

前提是发送方最后会 close(ch)。

30.3 单向 channel

func send(ch chan<- int) {
    ch <- 1
}

func recv(ch <-chan int) {
    fmt.Println(<-ch)
}
  • chan<- int:只发

  • <-chan int:只收

30.4****select

同时等待多个 channel 操作。

select {
case v := <-ch1:
    fmt.Println("ch1:", v)
case v := <-ch2:
    fmt.Println("ch2:", v)
default:
    fmt.Println("都没准备好")
}

这是 Go 并发模型里非常重要的语法。

31. 泛型(Generics)

Go 现在已经支持泛型;而 Effective Go 官方也明确说明它那篇文章较早,不覆盖泛型和 modules,要结合更新的规范与发行说明来看。

31.1 泛型函数

func PrintSlice[T any](items []T) {
    for _, v := range items {
        fmt.Println(v)
    }
}

调用:

PrintSlice([]int{1, 2, 3})
PrintSlice([]string{"a", "b"})

[T any] 表示类型参数 T,约束是 any。

31.2 泛型类型

type Box[T any] struct {
    Value T
}

使用:

b1 := Box[int]{Value: 10}
b2 := Box[string]{Value: "hello"}

31.3 约束

type Number interface {
    ~int | ~int64 | ~float64
}

func Add[T Number](a, b T) T {
    return a + b
}

这类写法适合封装工具库,但业务开发里不用一上来就泛型化。

32. 标签、字符串字面量、Rune

32.1 原始字符串

s := `hello
world`

反引号字符串会保留换行,不处理转义。

32.2 解释型字符串

s := "hello\nworld"

32.3 字符与 rune

r := '中'
fmt.Printf("%T\n", r) // int32 / rune

单引号表示 rune 字面量,不是字符串。

33. 作用域

Go 主要有这些作用域:

  • 包级作用域

  • 函数作用域

  • 代码块作用域

例子:

var global = "包级"

func main() {
    x := 1
    if true {
        y := 2
        fmt.Println(x, y)
    }
    // y 在这里不可见
}

短变量声明 := 还要小心遮蔽(shadowing)

err := doA()
if err != nil {
    return err
}

if err := doB(); err != nil {
    return err
}

第二个 err 是新的局部变量。

34. 标签语句与带标签的****break/continue

多层循环里非常有用。

Outer:
for i := 0; i < 3; i++ {
    for j := 0; j < 3; j++ {
        if j == 1 {
            break Outer
        }
    }
}

也可以 continue Outer。

35.range的常见对象

range 可用于:

  • array

  • slice

  • string

  • map

  • channel

  • 整数迭代形式也已纳入较新的语言能力与规范演进中,但业务最常用的仍是前面几种容器/通道场景。

35.1 遍历字符串

for i, r := range "你好Go" {
    fmt.Println(i, r, string(r))
}

注意这里拿到的是 rune,不是单字节。

36. 常见内建函数

Go 有一批预声明标识符和内建函数,开发中很常见。

最常用的:

len(x)     // 长度
cap(x)     // 容量
make(...)  // 创建 slice/map/chan
new(T)     // 分配零值并返回 *T
append(...)// 追加元素
copy(...)  // 拷贝切片
delete(m,k)// 删除 map 键
close(ch)  // 关闭 channel
panic(v)   // 抛出 panic
recover()  // 恢复 panic(defer 中)

例子:

p := new(int)
fmt.Println(*p) // 0

s := make([]int, 0, 10)
fmt.Println(len(s), cap(s))

37.newmake的区别

这个是 Go 初学者高频面试点。

new(T):

分配一块 T 类型零值内存,返回 *T

p := new(int) // *int

make(…):

只用于 slice、map、chan,返回初始化后的值本身,不是指针。

s := make([]int, 3)
m := make(map[string]int)
ch := make(chan int)

38. 结构体标签(tag)

很常用,尤其在 JSON、ORM、参数校验里。

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

这不是“运行时语法糖”,而是字符串元数据,常被 encoding/json 等包读取。

39.json编码解码最常见写法

这不是语言语法本身,但你开始做 Go 开发几乎一定会写。

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

u := User{Name: "Hua", Age: 18}

data, err := json.Marshal(u)
if err != nil {
    return
}

var u2 User
err = json.Unmarshal(data, &u2)
if err != nil {
    return
}

40. 面向对象在 Go 里怎么理解

Go 没有“类 class”,但有:

  • struct:承载数据

  • method:绑定行为

  • interface:抽象能力

  • embedding:复用能力

所以 Go 不是“不能面向对象”,而是不走 class 继承那套路子。官方也长期强调组合优于继承、用接口表达能力。

41. Go 最常见项目文件结构

入门阶段你可以先这样理解:

myapp/
  go.mod
  main.go
  internal/
  pkg/

但别一开始就搞很复杂的目录规范。很多 Go 项目完全可以先从:

myapp/
  go.mod
  main.go
  user.go
  service.go

开始,等代码多了再拆包。

42. Go 写 Web 服务最基础长什么样

这不是纯语法,但你看完这个就知道 Go 开发长什么样了。

package main

import (
    "encoding/json"
    "net/http"
)

type Resp struct {
    Message string `json:"message"`
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    resp := Resp{Message: "hello go"}
    _ = json.NewEncoder(w).Encode(resp)
}

func main() {
    http.HandleFunc("/hello", helloHandler)
    http.ListenAndServe(":8080", nil)
}

你已经能看到 Go 做服务端的基本套路:

  • 定义结构体

  • 写 handler

  • 返回 JSON

  • 启动 HTTP 服务

43. 新手必须掌握的 Go 开发习惯

Go 官方长期强调几件事:写清晰代码、让 gofmt 统一格式、用显式错误处理、接口从使用方抽象、保持包名简洁。Effective Go 虽然较早,不覆盖泛型和 modules,但这些核心风格仍然很有参考价值。

最重要的 7 条:

  1. 先写清楚,再谈抽象

  2. 优先组合,不迷信继承思维

  3. 错误显式处理,不吞错

  4. 能不用泛型时先不用

  5. 小接口优于大接口

  6. 不要过度封装

  7. 交给 gofmt 管格式

44. 新手最容易踩的坑

44.1nil map不能写

var m map[string]int
m["a"] = 1 // panic

要先 make。

44.2append忘了接返回值

s := []int{1, 2}
append(s, 3) // 没用

要写:

s = append(s, 3)

44.3 值接收者没改到原结构体

func (u User) SetName(name string) {
    u.Name = name
}

应改成指针接收者。

44.4 字符串按字节不是按字符

s := "你好"
fmt.Println(s[0]) // 取到的是第一个字节,不是“你”

44.5 把

panic

当普通错误处理

大多数场景应该返回 error。

44.6 一上来就写很重的抽象层

Go 更适合从简单代码逐步抽象。

45. 你学完这些后,已经能写什么

只要你理解了上面这些内容,你已经可以开始写:

  • CLI 工具

  • 文件处理脚本

  • HTTP API 服务

  • JSON 接口

  • 并发任务

  • 简单爬虫

  • WebSocket / TCP 基础服务

  • 数据库 CRUD 程序

这些都属于“能进行 Go 开发”的范围。Go 官方教程本身也是从模块、包、函数、依赖、运行命令这些核心环节带你入门。

46. 给你一个真正能上手的入门顺序

按这个顺序学,效率最高:

先学:

  1. 变量、常量、基本类型

  2. if、for、switch

  3. 函数、多返回值、defer

  4. 指针

  5. array、slice、map

  6. struct、方法

  7. interface、错误处理

  8. package / module

  9. goroutine / channel / select

  10. 泛型

然后立刻做 3 个小项目:

  1. 命令行记账本

  2. 本地 JSON 文件用户管理

  3. HTTP CRUD 服务

这样学得最快。

47. 一份最小 Go 语法速查表

// 变量
var a int = 1
b := 2

// 常量
const Pi = 3.14

// if
if a < b {
}

// for
for i := 0; i < 10; i++ {
}

// switch
switch a {
case 1:
default:
}

// 函数
func add(a, b int) int {
    return a + b
}

// 多返回值
func div(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("zero")
    }
    return a / b, nil
}

// 指针
func inc(n *int) { *n++ }

// 数组
arr := [3]int{1,2,3}

// 切片
s := []int{1,2,3}
s = append(s, 4)

// map
m := map[string]int{"a": 1}

// struct
type User struct {
    Name string
}

// 方法
func (u User) Say() {}

// 接口
type Speaker interface {
    Speak() string
}

// goroutine
go task()

// channel
ch := make(chan int)
ch <- 1
v := <-ch

48. 最后一句实话

真正关键不是把规范背下来,而是把下面这些吃透:

  • slice

  • map

  • struct

  • method

  • interface

  • error

  • goroutine + channel

  • package + module

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
Golang2025-07-11
Go语言strconv包:字符串和数值类型的相互转换
在实际开发中我们往往需要对一些常用的数据类型进行转换,如 string、int、int64、float 等数据类型之间的转换,Go语言中的 strconv 包为我们提供了字符串和基本数据类型之间的转换功能。 strconv 包中常用的函数包括 Atoi()、Itia()、parse 系列函数、format 系列函数、append 系列函数等,下面就来分别介绍一下。 string 与 int 类型之间的转换 字符串和整型之间的转换是我们平...
学习
Golang2025-06-11
深入理解 Go 中的 new() 和 make() 函数
在 Go 语言中, 和 是两个常用的函数,用于创建和初始化不同类型的变量。本文将深入探讨 和 的区别、使用场景以及底层实现原理。 引言 Go 中的 和 函数是用于创建和初始化变量的重要工具。 用于创建指定类型的零值变量,并返回该变量的指针。 用于创建并初始化引用类型的变量,如切片、映射和通道。 函数 函数的基本语法及用法。 创建的变量是指定类型的零值,并返回该变量的指针。 适用于创建引用类型以外的其他类型变量。 函数 函数的基本语法及用...
学习
Golang2025-06-10
Ubuntu 升级 golang 版本完美步骤
一、删除旧的版本(可选) 二、下载最新版本 三、设置环境变量 1、打开profile: 2、添加以下变量: 3、是环境立即生效 4、将环境立即生效载入脚本 先打开文件这个文件: 加入这个命令: 四、查看 go 环境变量 五、GO111MOUDLE和更改GOPROXY 六、查看 go 版本 ⚙️
学习
Golang2025-06-05
Go 自动升级依赖版本
🚀 Go 自动升级依赖版本 在 Go 语言项目中,依赖管理使用 Go Modules ( 和 )。如果想要 自动升级依赖 ,可以使用以下方法。 1\. 方式 1:升级所有依赖 🔹 作用: :升级所有 Go 依赖到最新的 次要版本(minor)或补丁版本(patch) 。 :升级所有项目内的依赖。 2\. 方式 2:升级指定依赖 🔹 作用: 只升级 这个依赖到最新版本。 如果你需要升级到 最新的主要版本(major version)...
学习
Golang2025-06-02
GO项目的打包和部署
在 Go 语言中,打包和部署应用非常简单,因为 Go 编译生成的可执行文件不依赖外部环境。以下是 打包发布和部署 Go 应用 的几种常见方式,以及一些最佳实践。 1\. 基本的打包和构建 构建可执行文件 你可以通过 命令将你的应用打包成一个可执行文件: 说明: 指定输出的可执行文件名(如果省略,输出名默认为当前目录名)。 如果没有错误,当前目录会生成一个可执行文件 (Windows 系统下是 )。 运行可执行文件: 2\. 打包不同平台...
学习
Golang2024-11-14
Golang 之 gorm 标签介绍
结构体标签 标签定义 Tag是结构体在编译阶段关联到成员的元信息字符串,在运行的时候通过反射的机制读取出来。 结构体标签由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔的,如下 key会指定反射的解析方式,ps: json(JSON标签) orm(Beego标签)、gorm(GORM标签)、bson(MongoDB标签)、form(表单标签)、binding(表单验证标签) search(搜索标签...
学习

评论

请登录后发表评论

去登录
加载评论中...

目录