欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 高考 > Go学习笔记

Go学习笔记

2025/9/15 20:21:21 来源:https://blog.csdn.net/wanger61/article/details/145284029  浏览:    关键词:Go学习笔记

一、基础语法

1. 变量
1. var identifier type
var a string = "Runoob"  // 没有初始化则默认为零值,声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误2. var v_name = value    // 根据值自行判定变量类型
var d = true3. v_name := value // 等价于 var identifier type = value4. var vname1, vname2, vname3 = v1, v2, v3    //多变量声明
5. vname1, vname2, vname3 := v1, v2, v3

命名规则:
1)声明在函数内部,是函数的本地值,类似private
2)声明在函数外部,是对当前包可见(包内所有.go文件都可见)的全局值,类似protect
3)声明在函数外部且首字母大写是所有包可见的全局值,类似public

2. 常量
1. const identifier [type] = value
const LENGTH int = 102. const (Unknown = 0Female = 1Male = 2
)

iota,特殊常量,可以认为是一个可以被编译器修改的常量。

iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

const (a = iotabc
)
// a=0,b=1,c=2
3. 运算符
& 返回变量存储地址
* 指针变量
ptr = &a     /* 'ptr' 包含了 'a' 变量的地址 */
fmt.Printf("*ptr 为 %d\n", *ptr)  // 输出a的值
4. 条件语句
switch marks {case 90: grade = "A"case 80: grade = "B"case 50,60,70 : grade = "C"default: grade = "D"  
}// switch 可以用来判断存储类型
switch i := x.(type) {case nil:  fmt.Printf(" x 的类型 :%T",i)                case int:  fmt.Printf("x 是 int 型")                      case float64:fmt.Printf("x 是 float64 型")          case func(int) float64:fmt.Printf("x 是 func(int) 型")                      case bool, string:fmt.Printf("x 是 bool 或 string 型" )      default:fmt.Printf("未知型")    }  
5. 循环语句
sum := 0
for i := 0; i <= 10; i++ {sum += i
}// 这样写也可以,更像 While 语句形式
for sum <= 10{sum += sum
}for {sum++ // 无限循环下去
}//For-each range 循环
strings := []string{"google", "runoob"}for i, s := range strings {fmt.Println(i, s)}// 读取 key 和 valuefor key, value := range map1 {fmt.Printf("key is: %d - value is: %f\n", key, value)}// 读取 keyfor key := range map1 {fmt.Printf("key is: %d\n", key)}// 读取 valuefor _, value := range map1 {fmt.Printf("value is: %f\n", value)}// range 迭代字符串时,返回每个字符的索引和 Unicode 代码点(rune)for i, c := range "hello" {fmt.Printf("index: %d, char: %c\n", i, c)}// 遍历通道ch := make(chan int, 2)ch <- 1ch <- 2close(ch)for v := range ch {fmt.Println(v)}
6. 函数
func function_name( [parameter list] ) [return_types] {函数体
}
func max(num1, num2 int) int {/* 定义局部变量 */var result intif (num1 > num2) {result = num1} else {result = num2}return result
}// Go 函数可以返回多个值
func swap(x, y string) (string, string) {return y, x
}

init函数:go语言中init函数用于包(package)的初始化,如初始化包里的变量等

  • 每个包可以拥有多个init函数
  • 包的每个源文件也可以拥有多个init函数
  • 同一个包中多个init函数的执行顺序go语言没有明确的定义
  • 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序。初始化顺序是先导入的包,然后是当前包中的 init 函数,如果有多个 init 函数,它们会按定义的顺序依次调用
  • init函数不能被其他函数调用,而是在main函数执行之前,自动被调用
7. 数组
var arrayName [size]dataType
var numbers [5]int
var numbers = [5]int{1, 2, 3, 4, 5}
numbers := [5]int{1, 2, 3, 4, 5}//  如果设置了数组的长度,可以通过指定下标来初始化元素
balance := [5]float32{1:2.0,3:7.0} // 将索引为 1 和 3 的元素初始化
8. 切片
// 可以声明一个未指定大小的数组来定义切片
var identifier []type
// make([]T, length, capacity)函数定义切片, capacity容量为可选参数
slice1 := make([]type, len)
// 通过下标切片
s := arr[startIndex:endIndex] 
// len() 和 cap() 函数获取长度和容量
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
//append() 和 copy() 函数
var numbers []int
numbers = append(numbers, 0) 
numbers = append(numbers, 2,3,4) // 向切片中添加元素numbers1 := make([]int, len(numbers), (cap(numbers))*2) // 创建切片 numbers1 是之前切片的两倍容量
copy(numbers1,numbers) // 拷贝 numbers 的内容到 numbers1
9. 结构体
type struct_variable_type struct {member definitionmember definition...member definition
}type Books struct {title stringauthor stringsubject stringbook_id int
}//一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:
variable_name := structure_variable_type {value1, value2...valuen}
或
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
// 结构体指针
var Book1 Books
printBook(&Book1)
func printBook( book *Books ) {fmt.Printf( "Book title : %s\n", book.title)fmt.Printf( "Book author : %s\n", book.author)fmt.Printf( "Book subject : %s\n", book.subject)fmt.Printf( "Book book_id : %d\n", book.book_id)
}
10. Map
/* 使用 make 函数 */
map_variable := make(map[KeyType]ValueType, initialCapacity)
m := make(map[string]int)// 使用字面量创建 Map
m := map[string]int{"apple": 1,"banana": 2,"orange": 3,
}v2, ok := m["pear"]  // 如果键不存在,ok 的值为 false,v2 的值为该类型的零值
// 删除键值对
delete(m, "banana")
11. 类型转换
// 数值类型转换
type_name(expression)var a int = 10
var b float64 = float64(a)// 字符串转整数
var str string = "10"
var num int
num, _ = strconv.Atoi(str) // 第一个是转换后的整型值,第二个是可能发生的错误,可以使用空白标识符 _ 来忽略这个错误// 字符串转浮点数
str := "3.14"
num, err := strconv.ParseFloat(str, 64)// 整数转字符串
num := 123
str := strconv.Itoa(num)// 浮点数转字符串
num := 3.14
str := strconv.FormatFloat(num, 'f', 2, 64)
12. 接口

Go 中没有关键字显式声明某个类型实现了某个接口
只要一个类型实现了接口要求的所有方法,该类型就自动被认为实现了该接口

接口的零值是 nil,一个未初始化的接口变量其值为 nil,且不包含任何动态类型或值

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

// 定义接口
type Shape interface {Area() float64Perimeter() float64
}// 定义一个结构体
type Circle struct {Radius float64
}// Circle 实现 Shape 接口
func (c Circle) Area() float64 {return math.Pi * c.Radius * c.Radius
}func (c Circle) Perimeter() float64 {return 2 * math.Pi * c.Radius
}func main() {c := Circle{Radius: 5}var s Shape = c // 接口变量可以存储实现了接口的类型fmt.Println("Area:", s.Area())fmt.Println("Perimeter:", s.Perimeter())
}

空接口:定义为 interface{},可以表示任何类型
任意类型都实现了空接口。常用于需要存储任意类型数据的场景,如泛型容器、通用参数等。

func printValue(val interface{}) {fmt.Printf("Value: %v, Type: %T\n", val, val)
}

接口类型转换

// 类型断言,将接口类型转换为指定类型
value.(type) 
value.(T)var i interface{} = "Hello, World"str, ok := i.(string)if ok {fmt.Printf("'%s' is a string\n", str)} else {fmt.Println("conversion failed")}// 类型转换,将一个接口类型的值转换为另一个接口类型
T(value)
// 定义一个接口 Writer
type Writer interface {Write([]byte) (int, error)
}// 实现 Writer 接口的结构体 StringWriter
type StringWriter struct {str string
}// 实现 Write 方法
func (sw *StringWriter) Write(data []byte) (int, error) {sw.str += string(data)return len(data), nil
}func main() {// 创建一个 StringWriter 实例并赋值给 Writer 接口变量var w Writer = &StringWriter{}// 将 Writer 接口类型转换为 StringWriter 类型sw := w.(*StringWriter)// 修改 StringWriter 的字段sw.str = "Hello, World"
}

接口可以通过嵌套组合,实现更复杂的行为描述

type Reader interface {Read() string
}type Writer interface {Write(data string)
}type ReadWriter interface {ReaderWriter
}
13. 错误处理

Go 标准库定义了一个 error 接口,表示一个错误的抽象,任何实现了 Error() 方法的类型都可以作为错误

type error interface {Error() string
}

使用 errors 包创建错误

import ("errors""fmt"
)func main() {err := errors.New("this is an error")fmt.Println(err) // 输出:this is an error
}// 函数通常在最后的返回值中返回错误信息,使用 errors.New 可返回一个错误信息
func Sqrt(f float64) (float64, error) {if f < 0 {return 0, errors.New("math: square root of negative number")}// 实现
}result, err:= Sqrt(-1)if err != nil {fmt.Println(err)
}

自定义错误

type DivideError struct {Dividend intDivisor  int
}func (e *DivideError) Error() string {return fmt.Sprintf("cannot divide %d by %d", e.Dividend, e.Divisor)
}func divide(a, b int) (int, error) {if b == 0 {return 0, &DivideError{Dividend: a, Divisor: b}}return a / b, nil
}func main() {_, err := divide(10, 0)if err != nil {fmt.Println(err) // 输出:cannot divide 10 by 0}
}
var ErrNotFound = errors.New("not found")func findItem(id int) error {return fmt.Errorf("database error: %w", ErrNotFound)
}func main() {err := findItem(1)// errors.Is检查某个错误是否是特定错误或由该错误包装而成。if errors.Is(err, ErrNotFound) {fmt.Println("Item not found")} else {fmt.Println("Other error:", err)}
}type MyError struct {Code intMsg  string
}func (e *MyError) Error() string {return fmt.Sprintf("Code: %d, Msg: %s", e.Code, e.Msg)
}func getError() error {return &MyError{Code: 404, Msg: "Not Found"}
}func main() {err := getError()var myErr *MyError// errors.As将错误转换为特定类型以便进一步处理if errors.As(err, &myErr) {fmt.Printf("Custom error - Code: %d, Msg: %s\n", myErr.Code, myErr.Msg)}
}

panic 和 recover

panic:
导致程序崩溃并输出堆栈信息。
常用于程序无法继续运行的情况。

recover:
捕获 panic,避免程序崩溃。

func safeFunction() {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()panic("something went wrong")
}
14. 内置函数

append – 用来追加元素到数组、slice中,返回修改后的数组、slice
close – 主要用来关闭channel
delete – 从map中删除key对应的value
panic – 停止常规的goroutine (panic和recover:用来做错误处理)
recover – 允许程序定义goroutine的panic动作
imag – 返回complex的实部 (complex、real imag:用于创建和操作复数)
real – 返回complex的虚部
make – 用来分配内存,返回Type本身(只能应用于slice, map, channel)
new – 用来分配内存,主要用来分配值类型,比如int、struct。返回指向Type的指针
cap – capacity是容量的意思,用于返回某个类型的最大容量(只能用于切片和 map)
copy – 用于复制和连接slice,返回复制的数目
len – 来求长度,比如string、array、slice、map、channel ,返回长度

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词