三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

02 Go 变量与类型学习笔记

02 Go 变量与类型学习笔记

Go 变量与类型学习笔记

1. var 声明变量

Go 使用var关键字声明变量,可以指定类型或让编译器推断:

packagemainimport"fmt"funcmain(){varmessage="Hello Variables!"fmt.Println(message)}

执行结果:

Hello Variables!

要点

  • var message = "Hello Variables!"— 省略类型时,编译器根据右值自动推断类型(此处推断为string
  • var message string = "Hello Variables!"— 显式指定类型
  • var message string— 只声明不赋值,变量获得零值(空字符串""
  • var声明可在函数内或函数外使用(包级别)

2. 短变量声明(:=)

:=是 Go 最常用的变量声明方式,只能在函数内部使用:

packagemainimport"fmt"funcmain(){count:=42fmt.Printf("Count: %d\n",count)}

执行结果:

Count: 42

要点

  • :=同时完成声明和赋值,编译器自动推断类型(此处推断为int
  • :=只能在函数内部使用,不能用于包级别变量
  • :=左侧必须至少有一个新变量,否则应使用=赋值
  • 对比varvar count = 42等价于count := 42,但:=更简洁

3. 批量声明变量(var 分组)

多个变量可以用var()分组声明,更清晰:

packagemainimport"fmt"funcmain(){var(name="Alice"age=30city="Boston")fmt.Printf("Name: %s, Age: %d, City: %s\n",name,age,city)}

执行结果:

Name: Alice, Age: 30, City: Boston

要点

  • var()分组写法适合声明多个相关变量,代码更整洁
  • 每个变量仍可以单独指定类型或省略类型让编译器推断
  • 包级别变量也常用分组写法:
    var(globalName="Go"globalAge=10)

4. 类型推断(Type Inference)

当变量声明时省略类型,Go 编译器根据右值自动推断:

packagemainimport"fmt"funcmain(){language:="Go"version:=1.21isActive:=truefmt.Printf("Language: %s %.2f, Active: %t\n",language,version,isActive)}

执行结果:

Language: Go 1.21, Active: true

要点

  • language := "Go"→ 推断为string
  • version := 1.21→ 推断为float64(Go 中浮点数字面值默认是float64,不是float32
  • isActive := true→ 推断为bool
  • 如果需要特定类型(如float32),必须显式声明:var version float32 = 1.21

5. 零值(Zero Values)

Go 中声明变量但不赋值时,变量自动获得该类型的零值

packagemainimport"fmt"funcmain(){varnamestringvarcountintvaractiveboolvarpricefloat64fmt.Printf("String: '%s', Int: %d, Bool: %t, Float: %.1f\n",name,count,active,price)}

执行结果:

String: '', Int: 0, Bool: false, Float: 0.0

要点

  • 各类型的零值:
    • string""(空字符串)
    • int0
    • boolfalse
    • float640.0
    • 指针、切片、映射、通道、接口、函数 →nil
  • Go 没有"未初始化变量"的概念,变量总是有确定的值
  • 这避免了 C 语言中未初始化变量带来的安全隐患

6. 常量(Constants)

常量用const声明,值在编译时确定,运行时不可修改:

packagemainimport"fmt"constPI=3.14159constAppName="GoForGo"funcmain(){fmt.Printf("App: %s, PI: %.5f\n",AppName,PI)}

执行结果:

App: GoForGo, PI: 3.14159

要点

  • const声明的值不可修改,尝试修改会编译报错
  • 常量不能用:=声明
  • 常量的值必须在编译时就能确定(不能是函数返回值等运行时结果)
  • 常量也可以分组声明:
    const(PI=3.14159AppName="GoForGo")
  • 特殊常量iota用于生成递增枚举值:
    const(Sunday=iota// 0Monday// 1Tuesday// 2)

7. Go 基本类型

Go 提供丰富的内置类型,变量声明时显式指定类型:

packagemainimport"fmt"funcmain(){varnamestring="Go"varversionfloat64=1.21varisOpenbool=truevarusersint=1000000fmt.Printf("Language: %s %.2f, Open: %t, Users: %d\n",name,version,isOpen,users)}

执行结果:

Language: Go 1.21, Open: true, Users: 1000000

要点

  • Go 的基本类型:
类别类型
整数int,int8,int16,int32,int64,uint,uint8uint64
浮点float32,float64
布尔bool
字符串string
字符byte(uint8 的别名),rune(int32 的别名,表示 Unicode 字符)
复数complex64,complex128
  • int在 64 位系统上是 64 位,32 位系统上是 32 位
  • float64是默认浮点类型,精度比float32更高
  • 显式指定类型时,var name string = "Go"var name = "Go"(推断)效果相同

8. 类型转换(Type Conversion)

Go 不支持隐式类型转换,所有跨类型转换必须显式进行:

packagemainimport("fmt""strconv")funcmain(){// These variables have different typesvarnumberint=42varpifloat64=3.14159varmessagestring="123"floatNumber:=float64(number)intPi:=int(pi)convertedNumber,_:=strconv.Atoi(message)fmt.Printf("Float: %.2f, Int: %d, Converted: %d\n",floatNumber,intPi,convertedNumber)}

执行结果:

Float: 42.00, Int: 3, Converted: 123

要点

  • 数值类型之间的转换:float64(number)intfloat64int(pi)float64int
  • int(pi)截断小数部分:3.14159 → 3(不是四舍五入)
  • 字符串与数值的转换需要strconv包:
    • strconv.Atoi("123")→ 字符串转整数,返回(int, error)
    • strconv.Itoa(123)→ 整数转字符串
    • strconv.ParseFloat("3.14", 64)→ 字符串转浮点数
    • strconv.FormatFloat(3.14, 'f', 2, 64)→ 浮点数转字符串
  • Go 不允许隐式转换:var f float64 = 42编译报错,必须写var f float64 = float64(42)
  • convertedNumber, _ := strconv.Atoi(message)_忽略了可能的错误,实际代码中应处理 error

9. 变量作用域(Variable Scope)

变量的可见范围取决于声明位置:包级别 > 函数级别 > 块级别:

packagemainimport"fmt"varglobalMessage="Global"funcmain(){localMessage:="Local"// This will create a new scopeiftrue{blockMessage:="Block"fmt.Printf("%s %s %s\n",globalMessage,localMessage,blockMessage)}// blockMessage is not accessible herefmt.Printf("%s %s\n",globalMessage,localMessage)}

执行结果:

Global Local Block Global Local

要点

  • 三层作用域:
    • 包级别:在所有函数外声明(var globalMessage = "Global"),整个包内可见
    • 函数级别:在函数内声明(localMessage := "Local"),该函数内可见
    • 块级别:在ifforswitch等代码块内声明(blockMessage := "Block"),只在该块内可见
  • 内层作用域可以访问外层变量(块内可以访问 local 和 global)
  • 外层作用域不能访问内层变量(函数外不能访问 blockMessage)
  • if true是一个永远为真的条件,仅用于演示块作用域

知识点总结

知识点关键概念
var 声明var name = value可在函数内外使用,可指定或省略类型
短变量声明name := value只能在函数内使用,自动推断类型
批量声明var ()分组声明多个变量,更整洁
类型推断省略类型时编译器根据右值推断,浮点默认float64
零值未赋值的变量自动获得零值:string→"", int→0, bool→false, float→0.0
常量const声明不可修改,编译时确定,支持iota枚举
基本类型int/float/bool/string/rune/byte,无隐式转换
类型转换必须显式转换:float64(i)int(f),字符串与数值用strconv
变量作用域包级 > 函数级 > 块级,内层可见外层,外层不可见内层
← 返回列表