Go Syntax Basics: Variables, Functions, Errors & Structs
var and short declarations, basic types, functions with multiple return values, idiomatic error handling, pointers, structs and methods — the grammar of Go.
Variables and Types
package main
import "fmt"
func main() {
// var 声明
var name string = "Go"
var port = 8080 // 类型推断
var timeout int // 零值 0
// 短变量声明(仅函数内)
host := "localhost"
// 常量
const Pi = 3.14159
// 基本类型
var i int = 42
var f float64 = 3.14
var b bool = true
var s string = "hi"
var by byte = 'A'
fmt.Println(name, port, timeout, host, i, f, b, s, by)
}
Go has no unused variables — the compiler rejects them. Every type has a zero value (0, false, ""), so nil-pointer dereference is harder to hit accidentally.
Functions and Multiple Return Values
// 多返回值是 Go 的惯例:值 + error
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("divide by zero")
}
return a / b, nil
}
// 命名返回值
func swap(a, b int) (x, y int) {
y = a
x = b
return // 裸 return
}
// 可变参数 + defer
func sum(nums ...int) (total int) {
defer func() { total++ }() // defer 延迟执行
for _, n := range nums {
total += n
}
return
}
// 函数是一等公民
var fn func(int) int = func(x int) int { return x * 2 }
Error Handling Idioms
Go does not use exceptions. Functions return errors and the caller decides: check immediately, wrap with context, or propagate up.
result, err := divide(10, 0)
if err != nil {
// 包装错误后向上传递(error wrapping)
return fmt.Errorf("calc failed: %w", err)
}
// panic/recover 仅用于真正不可恢复的场景
// 例如:程序启动配置错误、map 并发写
// defer + recover 模拟 try/catch(少用)
defer func() {
if r := recover(); r != nil {
log.Println("recovered:", r)
}
}()
errors.Is checks identity, errors.As extracts a typed error, and %w in fmt.Errorf wraps the cause. Modern Go code wraps errors with context at each layer.
Structs, Methods and Interfaces
type User struct {
ID int64
Name string `json:"name"` // 结构体标签
}
// 值接收者方法
func (u User) Greet() string {
return "Hi, " + u.Name
}
// 指针接收者方法(可修改字段)
func (u *User) Rename(n string) {
u.Name = n
}
// 接口:隐式实现(只要有这些方法就算实现)
type Greeter interface {
Greet() string
}
func hello(g Greeter) { fmt.Println(g.Greet()) }
func main() {
u := &User{ID: 1, Name: "Go"}
hello(u) // User 隐式实现了 Greeter
}
Interfaces are satisfied implicitly — no 'implements' keyword. This makes Go code decoupled: define small interfaces (io.Reader, error) where they are used, not where types are defined.
变量与类型
package main
import "fmt"
func main() {
// var 声明
var name string = "Go"
var port = 8080 // 类型推断
var timeout int // 零值 0
// 短变量声明(仅函数内)
host := "localhost"
// 常量
const Pi = 3.14159
// 基本类型
var i int = 42
var f float64 = 3.14
var b bool = true
var s string = "hi"
var by byte = 'A'
fmt.Println(name, port, timeout, host, i, f, b, s, by)
}
Go 不允许声明未使用的变量,编译直接拒绝。每个类型都有零值(0、false、""),降低了空指针误用风险。
函数与多返回值
// 多返回值是 Go 的惯例:值 + error
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("divide by zero")
}
return a / b, nil
}
// 命名返回值
func swap(a, b int) (x, y int) {
y = a
x = b
return // 裸 return
}
// 可变参数 + defer
func sum(nums ...int) (total int) {
defer func() { total++ }() // defer 延迟执行
for _, n := range nums {
total += n
}
return
}
// 函数是一等公民
var fn func(int) int = func(x int) int { return x * 2 }
错误处理惯例
Go 不用异常。函数返回 error,由调用方决定:立即处理、带上上下文包装,或继续向上传递。
result, err := divide(10, 0)
if err != nil {
// 包装错误后向上传递(error wrapping)
return fmt.Errorf("calc failed: %w", err)
}
// panic/recover 仅用于真正不可恢复的场景
// 例如:程序启动配置错误、map 并发写
// defer + recover 模拟 try/catch(少用)
defer func() {
if r := recover(); r != nil {
log.Println("recovered:", r)
}
}()
errors.Is 判断错误身份,errors.As 提取类型化错误,fmt.Errorf 的 %w 包装原因。现代 Go 代码会在每一层给错误补充上下文。
结构体、方法与接口
type User struct {
ID int64
Name string `json:"name"` // 结构体标签
}
// 值接收者方法
func (u User) Greet() string {
return "Hi, " + u.Name
}
// 指针接收者方法(可修改字段)
func (u *User) Rename(n string) {
u.Name = n
}
// 接口:隐式实现(只要有这些方法就算实现)
type Greeter interface {
Greet() string
}
func hello(g Greeter) { fmt.Println(g.Greet()) }
func main() {
u := &User{ID: 1, Name: "Go"}
hello(u) // User 隐式实现了 Greeter
}
接口是隐式实现的,没有 implements 关键字。这让 Go 代码高度解耦:在「使用处」定义小接口(io.Reader、error),而不是在「定义处」。