znlgis 博客

GIS开发与技术分享 — GDAL · GeoServer · PostGIS · QGIS · OpenLayers · Cesium · FreeCAD · NPOI

第03章 - 基础语法与数据类型

本章系统讲解 Go 的基础语法元素:变量、常量、基本数据类型、运算符以及类型转换,这是编写任何 Go 程序的根基。

3.1 程序结构与包

每个 Go 源文件都以 package 声明开头,表明它属于哪个包。同一目录下的所有文件必须属于同一个包。

package main

import (
    "fmt"
    "math"
)

func main() {
    fmt.Println(math.Pi)
}
  • 多个导入可以用括号分组书写。
  • 导入的包如果没有被使用,会导致编译错误——这是 Go 强制简洁的体现。
  • 同样,声明但未使用的局部变量也会导致编译失败。

3.2 变量声明

3.2.1 标准声明

使用 var 关键字声明变量:

var name string = "Go"
var age int = 15
var isStable bool = true

3.2.2 类型推断

如果提供了初始值,可以省略类型,由编译器自动推断:

var name = "Go"      // 推断为 string
var age = 15         // 推断为 int

3.2.3 短变量声明

在函数内部,最常用的是 := 短变量声明,它同时完成声明和初始化:

func main() {
    name := "Go"
    age := 15
    pi := 3.14
}

注意:= 只能在函数内部使用,不能用于包级别变量声明。

3.2.4 批量声明

var (
    host string = "localhost"
    port int    = 8080
    debug bool  = false
)

3.2.5 零值

Go 中所有变量在声明时若未显式初始化,都会被赋予该类型的零值,绝不会是未定义的随机值:

类型 零值
数值类型(int、float 等) 0
布尔类型 false
字符串 ""(空字符串)
指针、切片、map、channel、函数、接口 nil
var i int       // 0
var f float64   // 0.0
var s string    // ""
var b bool      // false
var p *int      // nil

3.3 常量

常量使用 const 声明,其值在编译期确定,不可修改:

const Pi = 3.14159
const (
    StatusOK = 200
    StatusNotFound = 404
)

3.3.1 iota 枚举

iota 是 Go 的常量计数器,在 const 块中从 0 开始,每行自增 1,常用于定义枚举:

const (
    Sunday = iota // 0
    Monday        // 1
    Tuesday       // 2
    Wednesday     // 3
    Thursday      // 4
    Friday        // 5
    Saturday      // 6
)

利用 iota 还能定义带计算的枚举,例如表示存储单位:

const (
    _  = iota             // 忽略 0
    KB = 1 << (10 * iota) // 1 << 10 = 1024
    MB                    // 1 << 20
    GB                    // 1 << 30
    TB                    // 1 << 40
)

3.4 基本数据类型

3.4.1 整型

Go 提供了丰富的整型,分为有符号和无符号两类:

类型 位数 范围说明
int8 / uint8 8 uint8 即 byte
int16 / uint16 16  
int32 / uint32 32 int32 即 rune
int64 / uint64 64  
int / uint 平台相关 32 位系统为 32 位,64 位系统为 64 位
uintptr 平台相关 存放指针的整数

建议:除非有特殊需求(如二进制协议、性能优化),整数一律使用 int

3.4.2 浮点型

  • float32:单精度,约 7 位有效数字。
  • float64:双精度,约 15 位有效数字,是默认和推荐的浮点类型。
var pi float64 = 3.141592653589793

由于浮点数存在精度问题,比较两个浮点数是否相等时应判断差值是否小于一个极小值,而非直接用 ==

3.4.3 复数

Go 原生支持复数类型 complex64complex128

c := complex(3, 4) // 3+4i
fmt.Println(real(c), imag(c)) // 3 4

3.4.4 布尔型

bool 类型只有 truefalse 两个值。注意 Go 中布尔值不能与整数互相转换。

3.4.5 字符串

字符串是不可变的字节序列,底层使用 UTF-8 编码:

s := "Hello, 世界"
fmt.Println(len(s))        // 13(字节数,中文每个占 3 字节)
fmt.Println(s[0])         // 72(byte 值)
  • 双引号字符串支持转义字符(\n\t 等)。
  • 反引号`)定义原始字符串,不转义,可跨行,常用于正则表达式或多行文本:
raw := `第一行
第二行	带制表符
路径: C:\Users`

3.4.6 byte 与 rune

  • byteuint8 的别名,表示一个字节。
  • runeint32 的别名,表示一个 Unicode 码点(字符)。

遍历字符串时,使用 range 会按 rune(字符)迭代,正确处理多字节字符:

for i, r := range "Go语言" {
    fmt.Printf("索引 %d: 字符 %c (码点 %d)\n", i, r, r)
}

3.5 运算符

3.5.1 算术运算符

+-*/%(取余)。注意整数相除会舍弃小数部分。

3.5.2 比较运算符

==!=<<=>>=,返回布尔值。

3.5.3 逻辑运算符

&&(与)、||(或)、!(非)。&&|| 具有短路求值特性。

3.5.4 位运算符

&(与)、|(或)、^(异或/按位取反)、<<(左移)、>>(右移)、&^(位清除)。

a, b := 12, 10
fmt.Println(a & b)  // 8
fmt.Println(a | b)  // 14
fmt.Println(a ^ b)  // 6
fmt.Println(a << 1) // 24

Go 没有 ++aa++ 作为表达式,a++a-- 只能作为独立语句使用,且没有前置形式。

3.6 类型转换

Go 是强类型语言,不存在隐式类型转换,所有类型转换都必须显式进行:

var i int = 100
var f float64 = float64(i)   // int -> float64
var u uint = uint(f)         // float64 -> uint

// 字符串与数字之间需要使用 strconv 包,不能直接转换
import "strconv"
s := strconv.Itoa(100)         // int -> string "100"
n, err := strconv.Atoi("100")  // string -> int

常见误区string(65) 不会得到 "65",而是得到字符 "A"(码点 65 对应的字符)。字符串与数字的转换必须使用 strconv 包。

3.7 fmt 格式化输出

fmt 包是最常用的输出工具,常用动词如下:

动词 含义
%v 默认格式输出值
%+v 输出结构体时带字段名
%#v Go 语法表示
%T 输出值的类型
%d 十进制整数
%f 浮点数
%s 字符串
%q 带引号的字符串
%t 布尔值
%p 指针地址
%x 十六进制
name, age := "Go", 15
fmt.Printf("%s 已经 %d 岁了\n", name, age)
fmt.Printf("类型: %T, 值: %v\n", age, age)

3.8 本章小结

本章覆盖了 Go 的基础语法核心:变量与常量声明、iota 枚举、基本数据类型(整型、浮点、字符串、byte/rune)、运算符以及显式类型转换。Go 强调简洁与显式——未使用的变量和导入会报错,没有隐式类型转换,这些设计使代码更安全、更易读。

下一章我们将学习流程控制语句与函数。