Golang 语法入门
Hello World
go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
变量
go
package main
import "fmt"
// 全局变量
var ans = 123
var cnt int
func main() {
// 单个局部变量
a := 114514
// 多个局部变量
b, c := 114, 514
fmt.Println(a, b, c)
fmt.Println(ans)
fmt.Println(cnt)
}
常量
使用 const
关键字
go
package main
import "fmt"
func main() {
const PI = 3.14
fmt.Println(PI)
}
函数
多返回值
go
package main
import "fmt"
// 前面是入参,后面是返回值
func getUpDown(n float64) (x float64, y float64) {
return n - 1, n + 1
}
func main() {
const PI = 3.14
fmt.Println(getUpDown(PI))
}
init 和 import 函数
引用传参
Go 默认为值传递,传指针可以实现引用传递。
- 函数中引用传递
*
- 变量指向地址
&
go
func swap(x *int, y *int) {
var temp int
temp = *x /* 保存 x 地址上的值 */
*x = *y /* 将 y 值赋给 x */
*y = temp /* 将 temp 值赋给 y */
}
func main() {
// ...
swap(&a, &b)
}
defer
defer 初识
return
后的调用,类似于 Java 的 finally。在 return 之后执行。
如果一个函数中有多个defer语句,它们会以栈顺序执行。
go
func Demo(){
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
defer fmt.Println("4")
}
func main() {
Demo()
}
bash
4
3
2
1
recover 错误拦截
运行时panic异常一旦被引发就会导致程序崩溃。
recover
函数可以在当前的程序从运行时 panic 的状态中恢复并重新获得流程控制权。
recover只有在defer调用的函数中有效。
go
package main
import "fmt"
func Demo(i int) {
// 必须放在最上面
defer func() {
err := recover()
if err != nil {
fmt.Println("err:", err)
}
}()
var arr [10]int
fmt.Println(arr[i])
}
func main() {
Demo(10)
fmt.Println("正常运行")
}
bash
err: runtime error: index out of range [10] with length 10
正常运行
slice 切片
slice 定义
Slice 的切片相当于动态数组
go
// 先定义再初始化
var arr []int
arr = make([]int, 3)
// 定义同时初始化
arr2 := make([]int, 3)
// 获取长度
len(arr)
// 获取容量
cap(arr)
append & copy
copy:拷贝切片
append:追加元素
对于追加不需要考虑容量限制,切片会自动扩容(原容量2倍)。
go
package main
import "fmt"
func main() {
var arr []int
// 需要赋值给自己(语法难崩...)
arr = append(arr, 1, 2, 3)
fmt.Println(arr)
}
Map 集合
吐槽:Map 叫集合、Slice 叫切片...终于知道为什么要说英文名了 😅🙏🏻
go
package main
import "fmt"
func main() {
// key: string
// value: int
m := make(map[string]int, 10)
m["apple"] = 1
m["banana"] = 2
// 字面量创建
n := map[string]int{
"apple": 1,
"banana": 2,
}
// 遍历 Map
for k, v := range m {
fmt.Printf("key=%s, value=%d\n", k, v)
}
// 删除元组
delete(n, "apple")
}
struct 结构体
结构体在函数入参中是值传递
go
package main
import "fmt"
type Book struct {
title string
price float64
}
func increasePrice(book *Book) {
book.price *= 1.2
}
func main() {
var book Book
book.title = "《Golang 从入门到字节》"
book.price = 100
fmt.Println(book)
// 结构体是值传递!!!
increasePrice(&book)
fmt.Println(book)
}
bash
{《Golang 从入门到字节》 100}
{《Golang 从入门到字节》 120}
面向对象
封装
Golang 不是面向对象编程的语言,使用结构体作为对象。
首字母大写表示 public,首字母小写表示 private。
go
package main
import "fmt"
type Student struct {
name string
age int
score int
}
func (s *Student) GetName() string {
return s.name
}
func (s *Student) SetName(name string) {
s.name = name
}
func (s *Student) Show() {
fmt.Println(*s)
}
func main() {
student := Student{
name: "wmh",
age: 22,
score: 100,
}
fmt.Println(student.GetName())
student.SetName("yixuan")
student.Show()
}
继承
😅 这语法要吐了
go
package main
import "fmt"
type Student struct {
name string
age int
score int
}
func (s *Student) GetName() string {
return s.name
}
func (s *Student) SetName(name string) {
s.name = name
}
func (s *Student) Show() {
fmt.Println(*s)
}
// 继承 Student
type CollageStudent struct {
Student
class string
}
// 重写子类方法
func (s *CollageStudent) Show() {
fmt.Println(*s)
}
func main() {
var stu CollageStudent
stu.age = 22
stu.class = "软件工程"
stu.name = "wmh"
fmt.Println(stu.GetName())
stu.SetName("yixuan")
stu.Show()
}
多态
多态三要素
使用 interface
接口实现多态
- 定义接口
- 子类实现了父类的全部接口方法
- 接口指针指向子类的具体数据变量
go
package main
import "fmt"
// 接口
type Person interface {
talk()
}
type Student struct {
name string
}
func (stu *Student) talk() {
fmt.Println(stu.name + ": student talk")
}
type Teacher struct {
name string
}
func (tea *Teacher) talk() {
fmt.Println(tea.name + ": teacher talk")
}
func main() {
var p1, p2 Person
p1 = &Student{"wmh"}
p1.talk()
p2 = &Teacher{"yx"}
p2.talk()
}
bash
wmh: student talk
yx: teacher talk
空接口
可以使用 interface{}
引用任意类型数据(类似于 Java 的 Object,或者 TS 的 any)
go
package main
import "fmt"
func myPrint(arg interface{}) {
fmt.Println("------")
fmt.Println(arg)
fmt.Println("------")
}
func main() {
n := 114514
str := "wahaha"
myPrint(n)
myPrint(str)
}
反射
类型断言
将空接口类型(类比 Object)判断并转换成具体子类
go
func main() {
var x interface{} = 114514
n, ok := x.(int)
fmt.Println(n, ok)
// 114514 true
var y interface{} = "114514"
m, ok := y.(int)
fmt.Println(m, ok)
// 0 false
}