乱点技能树之-go语言笔记篇

系统仍旧是廉颇老矣的windows7,所以很多软件的新版本都没法运行,就像go已经出到了1.26版本,但win7上仅支持1.20.14,再往上就不受支持了,所以下方的代表仅在上述版本中验证通过。学习go语言的第一感受是,go语言取消了c++里两者皆可的表达,而直接帮用户选择了使用频率更高的其中一种表达方式。

go1.20.14安装版

安装版的直接无脑下一步就好,暂时就不挑战手动配置环境了,怕耽误自己本就如风中残烛般的学习热情。安装完后可以直接在cmd或者powershell中运行go指令,就很方便,这里更推荐powershell,cmd部分指令无法正确运行。

创建工作文件夹

比如博主准备在d盘根目录下建立一个工作文件夹:

mkdir goPress
cd goPress
//这会创建一个 go.mod 文件,用来管理你的项目依赖
//注意这里的init后面的命名会影响到导入包的路径名称
go mod init goPress
//创建一个main.go文件
New-Item -ItemType File -Path main.go
//上述的指令可以简写为
ni main.go -type file

接下来可以随便找个文本编辑器来编辑这个go文件了,这里博主使用的是sublime。

你好,世界

国际惯例运行一个Hello world!,注意go语言不需要在行末添加分号,将以下语句保存至main.go

package main

import "fmt"

func main() {
    fmt.Println("你好,世界!")
}

然后在powershell里运行如下指令,我们就能看见经典的入门案例的输出了;

//下面的"main.go"可以 简写为 "."
PS D:\goPress> go run main.go

常量与变量

//定义变量
var identifier type = value
var identifier1, identifier2 type = value1, value2
//定义常量
const identifier [type] = value

运算符

运算符和c++很像,有c++基础的应该会觉得很亲切,其原因可能是因为其创始人都深受C语言影响:

  • Ken Thompson:B语言作者、C语言共同作者、Unix之父
  • Rob Pike:贝尔实验室Unix团队核心成员
  • Robert Griesemer:也有深厚的C/系统编程背景

与c++主要差异如下:
无三元运算符
无指针算术
无隐式类型转换
增加channel运算符 <- 和位清空 &^
++/-- 只能后缀且为语句
......

循环与判断

循环语句:

//常规用法
for init; condition; post { }
//类似while,顺便一提,go里没有while
for condition { }
//无限循环
for { }

数组的遍历

func main(){
    chars:=[]string{"a","b","c","d","e"}
    for key,value:=range chars{
        fmt.Println(key , value)
    }
    for key:=range chars{
        fmt.Println(key)
    }
    for _,value:=range chars{
        fmt.Println(value)
    }
}

判断语法:

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
} else {
  /* 在布尔表达式为 false 时执行 */
}

函数

func function_name( [parameter list] ) [return_types] {
   函数体
}

func:函数由 func 开始声明;
function_name:函数名称,参数列表和返回值类型构成了函数签名;
parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数;
return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的;
函数体:函数定义的代码集合。

需要注意的是,Go 允许函数返回多个值。

数组与切片

在 Go 语言中,数组和切片的核心定义区别在于:长度是否固定。

func main() {
    var arr1 [5] int
    var arr2 = [3]string{"a","b","c"}
    var arr4 = [3][3]int{
        {1,2,3},
        {4,5,6},
        {7,8,9},
    }
    fmt.Println(arr1)
    fmt.Println(arr2)
    fmt.Println(arr3)
    fmt.Println(arr4)
}

数组是定长的值类型,切片是变长的引用类型。在实际开发中,切片远比数组常用。

var s []int     // 不指定长度,长度可变
s = append(s, 1) // 可动态增加元素

切片的扩容规则

因为 go 的切片扩容策略:初始容量:5(刚好装下 1,2,3,4,5),追加第6个元素时:容量不足,触发扩容。
go 扩容规则:当容量 < 1024 时,通常翻倍(5 → 10),当容量 ≥ 1024 时,增长约 25%。

指针

go有选择性地限制了指针的某些危险特性(别说危险特性了,安全特性博主也没学明白呢)。

func main() {
    var a,b int = 1,2
    var p1 *int = &a
    var p2 *int = &b
    fmt.Println(a,b)
    swap(p1,p2)
    fmt.Println(a,b)
}

func swap(a,b *int){
    *a,*b=*b,*a
}

结构体

type Books struct {
    title string
    author string
    subject string
    bookid int
}


func main(){
    var book1 = Books{
        title: "a",
        author: "b",
        subject: "c",
        bookid: 0,
    }

    var book2 Books
    book2.title = "d"
    book2.author = "e"
    book2.subject = "f"
    book2.bookid = 1
    fmt.Println(book1, book2)
}

range范围

Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:

for key, value := range oldMap {
    newMap[key] = value
}

Map(集合)

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,遍历 Map 时返回的键值对的顺序是不确定的。在获取 Map 的值时,如果键不存在,返回该类型的零值,例如 int 类型的零值是 0,string 类型的零值是 ""。Map 是引用类型,如果将一个 Map 传递给一个函数或赋值给另一个变量,它们都指向同一个底层数据结构,因此对 Map 的修改会影响到所有引用它的变量。

func main() {
    var site = make(map[string]string,10)
        site["google"]="谷歌"
        site["baidu"]="百度"
        site["abddb"]="小鸟数据"
        site["wiki"]="维基"
    
    for key,value := range site {
        fmt.Println(key,"站点名称是",value)
    }
}

递归

学习到递归的内容,说明这门语言要开始折磨你了:

package main

import "fmt"

var arr = [100]int{0,1}

func digui(n int) int {
    if n == 1 {
        return 1
    }
    if arr[n]!=0 {
        return arr[n]
    }else{
        arr[n] = n * digui(n - 1)
        return arr[n]
    }
}

func main() {
    digui(10)
    for i:=0;i<10;i++{
        fmt.Println(arr[i])
    }
    
}

闭包

闭包(Closure)这一概念,在一些语言中又被称为 Lambda 表达式,与匿名函数一起使用,闭包 = 函数 + 环境引用。看下面一个例子:

package main

import "fmt"

func Exp(n int) func() int {
    e := 1
    return func() int {
        temp := e
        e *= n
        return temp
    }
}

func main() {
    grow := Exp(2)
    for i := 1; i < 10; i++ {
        fmt.Println("2^", i, "=", grow())
    }
}

利用闭包实现斐波那契数列的实例:

package main

import "fmt"

func Fib(n int) func() int {
    i := 0
    a, b, c := 1, 1, 2
    return func() int{
        if(i>n){
            return -1
        }else if i<2{
            f := i
            i++
            return f
        }else{
            i++
            a,b = b,c
            c = a+b
            return a
        }
    }
}

func main(){
    a:=Fib(10)
    for i:= a();i!=-1;i=a(){
        fmt.Println(i)
    }
}

数据类型转换

源类型 目标类型 转换方式 注意事项
int float64 float64(i) 可能产生小数部分
float64 int int(f) 截断小数,不是四舍五入
int string strconv.Itoa(i) 不要用 string(i)(会转为Unicode字符)
string int strconv.Atoi(s) 需要处理 error
string []byte []byte(s) 复制数据
[]byte string string(b) 复制数据
interface{} 具体类型 value.(Type) 使用 ok 模式避免 panic

接口

接口(interface)是 Go 语言中的一种类型,用于定义行为的集合,它通过描述类型必须实现的方法,规定了类型的行为契约。Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。Go 的接口设计简单却功能强大,是实现多态和解耦的重要工具。接口可以让我们将不同的类型绑定到一组公共的方法上,从而实现多态和灵活的设计。

接口常见用途

  • 多态:不同类型实现同一接口,实现多态行为。
  • 解耦:通过接口定义依赖关系,降低模块之间的耦合。
  • 泛化:使用空接口 interface{} 表示任意类型。

接口实例

package main

import "fmt"
import "math"

type Shape interface {
    area() float64
}

type Circle struct {
    radius float64
}

type Square struct {
    lenth float64
    width float64
}

func (c Circle) area() float64 {
    return math.Pi * c.radius * c.radius
}

func (s Square) area() float64 {
    return s.lenth * s.width
}

func main() {
    var s = Square {
        lenth : 6.0,
        width : 5.1,
    }
    var c = Circle {
        radius : 10,
    }
    fmt.Println(s.area())
    fmt.Println(c.area())
}

错误处理

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。Go 语言的错误处理采用显式返回错误的方式,而非传统的异常处理机制。这种设计使代码逻辑更清晰,便于开发者在编译时或运行时明确处理错误。Go 的错误处理主要围绕以下机制展开:

  • error 接口:标准的错误表示。
  • 显式返回值:通过函数的返回值返回错误。
  • 自定义错误:可以通过标准库或自定义的方式创建错误。
  • panic 和 recover:处理不可恢复的严重错误。

一个错误演示

package main

import "fmt"
import "errors"

func power(x int) (int, error) {
    if x > 10 {
        return 0 , errors.New("too big")
    } else {
        return x * x , nil
    }
}

func main() {
    var res int
    var err error
    res,err = power(11)
    if err != nil {
        fmt.Println("计算出错:", err)
        return
    }
    fmt.Println(res)
}

标签: go语言

移动端可扫我直达哦~

推荐阅读

thumbnail 2026-06-04

go语言gin框架的学习笔记

上半年尝试制作了一个微信小程序,通过小程序请求后台服务器,服务器负责组装好用户需求的mp3文件,然后返回给用户播放地址,以实现一个简单的听写功能。其中后台的逻辑基本都是通过deepseek实现的,虽然成功跑通了,但是一直想从头手搓一遍...

少儿编程 go语言

thumbnail 2026-06-02

提升读写性能,go语言的bufio包

最近在尝试学习go语言,想去洛谷做几道题吧,结果前几个答案是正确的,最后两个报了超时,标准输入输出fmt存在读写性能上的缺陷。deepseek推荐了这个bufio包。bufio 包的核心功能bufio 提供缓冲 I/O,通过减少系统调...

少儿编程 go语言

thumbnail 2026-05-30

fmt,Go 语言自带的格式化输入输出包

fmt 可以理解为 Format(格式)的缩写——因为它擅长格式化数据(比如把数字嵌进句子中间)。fmt 就是 Go 语言的"终端对话工具",让你能在屏幕上显示东西,也能从键盘获取输入。fmt包的常用指令 概念对应 fmt 函数标准输...

少儿编程 go语言