惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
博客园_首页
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
B
Blog RSS Feed
D
Docker
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
Recent Announcements
Recent Announcements
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
A
About on SuperTechFans
The GitHub Blog
The GitHub Blog
G
Google Developers Blog
V
V2EX
量子位
雷峰网
雷峰网
月光博客
月光博客
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog

BlogFinder

日常漫步 Vol.24 之漫步前山河 - 雅余 周报 #1-聊聊本周的收获 - Edwin's Blog 我的OpenCode必装插件与Skill Write Something 掌中之物未必在掌握之中 · CRIVU PiliNara,一个更顺手的 PiliPlus 分支 「NekoEcho」:做一个必有回响的猫娘主题博客 2026-05 书影音总结 简化博客主题 - 安迪 我第一次发布 npm 包 拾花小记#45:中考前的二三事 – 小改学习志 黛西花园5月游 #18 枇杷又熟了的五月月报 一些奇奇怪怪的需求?word仿方正书版的几个小操作 - Xiobb's Blog 0419 御温泉之旅 修复了一些bug,网站基本上趋于稳定了 - 新锐博客 又回到四十年前 如何定义成功 迷鹿屋2026已重新上线 科技冰火两重天+一周回顾 ${title} 热度退了,我反而用得更深了-咕咚同学 我到底该不该换个域名? 随身WIFI折腾记 - 安迪 博客撰写体验提升——hexo pro插件 为什么不用相机把屏幕上的接关密码拍下来? 国清寺与天台山 – Ouroboros ★★★★☆《挽救计划》——久违的经济上行感 - Davidの3号基地 删除右键“打开方式”里多余选项 第三周刊_No.53|一切都会被支付两次
golang学习之路:从入门到实践
santisify · 2026-06-20 · via BlogFinder

本人比较看重go的简洁性、跨平台不依赖运行时环境以及高并发(都是相对于Java),同时,我也比较侧重于后端开发,毕竟大部分理工男(懂的都懂)

我也算是开始自己的go语言学习了,但愿不要想java那样…

基础语法#

变量和常量数据类型#

//常量定义
const (
	StatusOK           = iota + 1    //iota是go语言的一个预定义标识符,表示常量生成器,在const关键字出现时被重置为0,并在每个const声明中自动递增。     
	StatusBadRequest                 //2
	StatusUnauthorized               //3
	MB                 = 1024 * 1024 //1048576
)

//变量定义
func main() {
	var str1 string = "Hello Go 1" //标准定义
	var str2 = "Hello Go 2"        //类型推断

	str3 := "Hello Go 3"          //短定义(通常用于函数中)
	fmt.Println(str1, str2, str3) //output:Hello Go 1 Hello Go 2 Hello Go 3
	str1, str2 = str2, str1       //交换str1与str2的值
	fmt.Println(str1, str2, str3) // output:Hello Go 2 Hello Go 1 Hello Go 3
}

//空值
func testNonInitValue() {
	var a int
	var b string
	var c float64
	fmt.Println(a, b, c) //output: 0 “” 0
	//上一行b输出的结果代表b的值是一个空字符串,而不是null或者undefined。
}


//至于类型转换,认真学过Java都知道
...

//类型自定义
type ll int64 // 定义一个新的类型ll,它的底层类型是int64
//为ll类型实现String方法,使其满足fmt.Stringer接口
func (l ll) String() string {
	return fmt.Sprintf("%d", l)
}
//结构体
type UserValue struct {
	name  string
	age   int
	email string
}
//同理,结构体也可以实现String方法
func (u UserValue) String() string {
	return fmt.Sprintf("name:%s, age:%d, email:%s)", u.name, u.age, u.email)
}
// slice
var arr [3]int       //只定义,为使用 output: 0,0,0
b := [3]int{1, 2, 3} //临时定义,并且附上初值 output:1,2,3
var c []int          //不定长
c1 = append(c, 1,2,3,4,5)
c2 := []int{1,2,3,4,5}
sc1 := make([]int, 0, len(c1)) // make函数创建一个长度为0,容量为len(c1)的切片
sc2 := new ([]int) // new函数创建一个指向长度为0的切片的指针

//map 键值对
m1 := map[string]int{"a": 1, "b": 2} //定义并初始化一个map output: map[a:1 b:2]
m2 := make(map[string]int)              //使用make函数创建一个空的map
m2["c"] = 3 //向map中添加一个键值对
for k, v := range m1 { // 使用range关键字遍历map,k代表键,v代表值
    fmt.Printf("key: %s, value: %d\n", k, v) //output: key: a, value: 1 \n key: b, value: 2
}

go

流程控制#

//if语句
if x > 0 {
    fmt.Println("x is positive")
} else if x < 0 {
    fmt.Println("x is negative")
} else {
    fmt.Println("x is zero")
}

//switch语句
switch day := time.Now().Weekday(); day {
case time.Monday:
    fmt.Println("It's Monday")
case time.Tuesday:
    fmt.Println("It's Tuesday")
default:
    fmt.Println("It's another day")
}

//for循环
for i := 0; i < 5; i++ {
    fmt.Println(i) //output: 0 1 2 3 4
}

//goto语句
func example() {
    fmt.Println("Start")
    goto Skip
    fmt.Println("This will be skipped")
Skip:
    fmt.Println("End")
}
//output: Start \n End

//select语句
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
    time.Sleep(1 * time.Second)
    ch1 <- "Hello from channel 1"
}()
go func() {
    time.Sleep(2 * time.Second)
    ch2 <- "Hello from channel 2"
}()
select {
case msg1 := <-ch1: 
    fmt.Println(msg1) //output: Hello from channel 1
case msg2 := <-ch2:
    fmt.Println(msg2) //output: Hello from channel 2
case <-time.After(3 * time.Second):
    fmt.Println("Timeout")
}

go

函数和方法#

//函数定义
func add(a int, b int) int {
	return a + b
}
//函数调用
result := add(3, 5) //output: 8
//方法定义
type Rectangle struct {
	width  float64
	height float64
}
func (r Rectangle) Area() float64 {
	return r.width * r.height
}
//方法调用
rect := Rectangle{width: 4, height: 5}
area := rect.Area() //output: 20

// 匿名函数
func() {
	fmt.Println("This is an anonymous function")
}() //output: This is an anonymous function

// 闭包
func makeAdder(x int) func(int) int {
	return func(y int) int {
		return x + y
	}
}
add5 := makeAdder(5)
result := add5(3) //output: 8

//可变参数
func sum(nums ...int) int {
	total := 0
	for _, num := range nums {
		total += num
	}
	return total
}
result := sum(1, 2, 3, 4) //output: 10

go

指针#

//指针定义
var p *int //定义一个指向int类型的指针
//指针赋值
x := 10
p = &x //将变量x的地址赋值给指针p
//指针解引用
value := *p //通过指针p获取x的值 output: 10
//指针修改值
*p = 20 //通过指针p修改x的值
fmt.Println(x) //output: 20

//指针与函数
func increment(n *int) {
	*n++ //通过指针n修改传入的值
}
num := 5
increment(&num) //传入num的地址
fmt.Println(num) //output: 6	

//指针与结构体
type Point struct {
	x int
	y int
}
p1 := Point{x: 1, y: 2}
p2 := &p1 //创建一个指向p1的指针
p2.x = 3 //通过指针p2修改p1的x值
fmt.Println(p1) //output: {3 2}

//指针与切片
func modifySlice(s []int) {
	s[0] = 100 //修改切片的第一个元素
}
slice := []int{1, 2, 3}
modifySlice(slice) //传入切片
fmt.Println(slice) //output: [100 2 3]

//二级指针
x := 10
p := &x
pp := &p
fmt.Println("x:", x, "p:", p, "pp:", pp, "**pp:", **pp) //output: x: 10 p:随机地址 pp: 随机地址 **pp: 10

go

错误处理#

//error类型
type error interface {
	Error() string
}

//defer语句
func example() {
	defer fmt.Println("This will be printed last")
	fmt.Println("This will be printed first")
}//output: This will be printed first \n This will be printed last

//panic和recover
func example() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered from panic:", r)
		}
	}()
	panic("Something went wrong") //触发panic
	fmt.Println("This will not be printed")
}//output: Recovered from panic: Something went wrong

go

Error样例:

package main

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

const (
	TimeFmt = "2006-01-02 15:04:05"
)

func main() {
	username, err := queryDatabase(100)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(username)
	}

	err = readFile("test.txt")
	if err != nil {
		fmt.Println(err)
	}

	a := []int{2, 4, 1, 24, 4, 32, 1, 243, 65, 43, 765, 23, 234}
	res, err := safeAccess(a, 100)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(res)
	}

	defres := deferReturn()
	fmt.Println("deferResult:", defres)
}

type BusinessError struct {
	Code    int
	Message string
	Time    time.Time
}

func (e *BusinessError) Error() string {
	return fmt.Sprintf("错误代码: %d \n 消息: %s \n 时间:%s \n",
		e.Code, e.Message, e.Time.Format(TimeFmt))
}

func queryDatabase(userID int) (string, error) {
	if userID <= 0 {
		return "", &BusinessError{
			Code:    400,
			Message: "用户不存在",
			Time:    time.Now(),
		}
	}
	if userID == 999 { //数据库连接超时
		return "", &BusinessError{
			Code:    401,
			Message: "数据库连接超时",
			Time:    time.Now(),
		}
	}
	return "李四", nil
}

func readFile(fileName string) error {
	file, err := os.Open(fileName)
	if err != nil {
		return fmt.Errorf("打开文件失败: %w", err)
	}
	defer file.Close()
	buf := make([]byte, 1024)
	_, err = file.Read(buf)
	if err != nil {
		return fmt.Errorf("读取文件失败: %w", err)
	}
	return nil
}

func safeAccess(arr []int, index int) (result int, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("panic: %v", r)
		}
	}()
	return arr[index], nil
}

func deferReturn() (result int) {  
	defer func() {  
		result++
	}()
	return 10
}

go