跳到主要内容

1.1-语言基础语法

Create by fall on 24 Sep 2025 Recently revised in 24 Oct 2025

Go

安装

下载

数据类型

// 整数类型
int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr
byte // uint 8 别名
rune // int32 别名

// 浮点数类型
float32 、float64
// 复数类型
complex64
complex128
// bool
bool
// 字符串类型
string

语法

从 hello world 开始

// main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello world")
}
// 定义变量
func foo(){
// 有初始值
a := 54
var b = 211
// 无初始值
var c int
c = 10
const mouse = 1 // const 只能声明简单类型
// 如果不进行初始化,会有一些默认值
var i int // 0
var f float64 // 0
var b bool // false
var s string // ""

x := i + 7 // 7
y := !b // true
z := s + "string" // string
}
// 顶级作用域,必须要使用 var 进行定义
var mvp = 2323

使用 Printf 输出不同的类型

// fmt.Printf()
// %T 可以输出对应类型,比如
func main(){
c := false
fmt.Printf("c 的类型为 %T",c)
}

运算符

和其他语言基本保持一致

// + - * /
// % < > <= >= ==
// && ||
// += -= i++ i--

函数声明

func sum(a int,b int)int{
return a + b
}
// 交换参数位置
func swap(a,b int)(int,int){
return b,a
}
func sum(a int,b int, transform func(init) int){
return transform(a),transform(b)
}

数组

func main(){
// 固定长度数组
a := [5]int{1,2,3,4,5}
// 可变长度数组,也叫切片,slice
a := make([]int,0) // 等价于 a := []int{1,2,3,4,5}
a = append(a,1,1,2,3) // 向 a 中插入数据
// 切片
c := [6]int{1,2,3,4,5,6}
d := c[1:4] // [2 3 4]
// 获取切片长度
len(c) // 3
// 容量
cap(c) // 6
}

切片

  result2 := make([]int, 0, 1000) // 预分配容量
for i := 0; i < 1000; i++ {
result2 = append(result2, i*2) // 不会重新分配内存
}

Map

map 同切片 slice,会在修改时,一并修改指向的内容

func main(){
// 定义一个 Map
map1 := map[string]int{
"a":1,
"b":3,
}
fmt.Println(map1)
// 删除条目
delete(map1, "a")
// map 的大小
someVal := map1["David"]
fmt.Println(someVal) // 0

// 判断一个值是否存在
getVal, isExists := map1["baobao"]
if !isExists {
fmt.Println("baobao is undefined")
}
}

结构

type Point struct{
X int
Y int
}
// & 表示对应数据的指针地址,* 表示地址中的数据
func (p *Point) SetPoint(x , y int){
p.X = x
p.Y = y
}
type Person struct {
name string // ""
age int // 0
}
p := Person{} // Creates a Person with empty string name and age 0
func main (){
p := Point{1,2}
fmt.Println(p)
p.SetPoint(2,3)
p.X = 5
}

struct 上增加新的方法

type Rectangle struct {
length float64
width float64
}
func (r Rectangle) Area() float64 {
return r.length * r.width
}
func (r *Rectangle) Double() {
r.length = r.length * 2
r.width = r.width * 2
}
func main() {
r := Rectangle{
length: 4,
width: 5,
}
fmt.Println(r.Area()) // 20
r.Double()
fmt.Println(r.Area()) // 80
// 为了方便使用 go 将 r.Area() 自动转换为 (&r).Double()
}

指针

在 go 中,几乎一切赋值的内容都是对应的值,slices, maps, channels 除外

type Point struct {
X int
Y int
}
func main (){
p := Point{1,2}
fmt.Println(p)
q := p
q.X = 5
// 此时赋值,两者不会干扰(默认按值赋值)
fmt.Println(q) // 5,2
fmt.Println(p) // 1,2

w := &p
w.X = 10
fmt.Println(*w) // 10,2
fmt.Println(p) // 10,2
// 在 go 中,任何为空的指针,都为 nil
// & 用来获取数据的地址,* 用来获取该地址中的值
// 使用 * 来对对象解引用的时候,如果指针为 nil,会导致异常
}
// 取地址符,对 int 等简单类型也适用
func modifyValue(x *int) {
*x = 100
}

y := 42
modifyValue(&y)
fmt.Println(y) // 100

接口

type Shape interface {
Print()
}
type Rectangle struct {}
type Triangle struct {}
func (r Rectangle) Print(){
fmt.Println("矩形")
}
func (t Triangle) Print(){
fmt.Println('三角形')
}

func main(){
var s Shape
s = Rectangle{}
s.Print() // 矩形
s = Triangle{}
s.Print() // 三角形
}

接口的实现

package main
import (
"fmt",
"math"
)
// interface 类型的接口,用于实现
type Shape interface {
area() float64 // 面积
perimeter() float64 // 周长
}
type Rectangel struct {
width float64
height float64
}
func (r *Rectangle) area() float64{
return r.width * r.height
}
func (r *Rectangle) perimeter() float64 {
return 2 * (r.width + r.height)
}

type Circle struct {
radius float64
}
func (c *Circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c *Circle) perimeter() float64{
return 2 * math.Pi * c.radius
}
func printArea(s Shape){
fmt.Println(s.area())
}
func main(){
r := &Rectangle{
height:20,
width:12,
}
c := &Circle{
radius: 3,
}
fmt.Println("Rectangle area:")
printArea(r)

fmt.Println("Circle area:")
printArea(c)
}

错误处理

func main(){
n, err := fmt.Println("ddd")
if err != nil {
//
}else {
// code
}
}

并发

func func1(){
time.Sleep(500* time.Milliscond)
fmt.Println("func1")
}
func func2(){
fmt.Println("func2")
}

func main(){
// go 关键字用来创建一个新的线程来执行内容
go func2()
func1()
}

Channels

func func1(ch chan string){
ch <- "函数1"
}
func func2(ch chan string){
ch <- "函数1"
}
func main(){
ch := make(chan string)
go func2(ch)
res1 := <-ch
go func1(ch)
res2 := <-ch
fmt.Println(res1,res2 )
}

断言

// 对类型进行断言
var s Shape
s = &Circle {
radius: 12
}
c,ok = s.(*Circle) // c 的类型为 Circle
fmt.PrintLn(c,ok) // &{12} true
rect,ok = s.(*Rectangle) // c 进行 Rectangle 断言
fmt.PrintLn(rect,ok) // <nil> false

// 对简单类型进行断言
var i interface{} = "hello"

s, ok := i.(string)
fmt.Println(s, ok)

f, ok := i.(float64)
fmt.Println(f, ok)

逻辑语句

判断

func main(){
a :=10
if a> 10{

}else if m:=55; a >2{ // 可以初始变量,只在括号内可用

}else {

}
}

循环

func main (){
for i :=1 ;i<5;i++ {
fmt.Println("dididi, %d", i)
}
var j = 1
for j<5 {
fmt.Println("dsa")
j++
}
// 同时初始化多个变量
for i, j := 0, 10; i < j; i, j = i+1, j-1 {
fmt.Printf("i=%d, j=%d\n", i, j)
}
// 类似 while (count > 0)
for count > 0 {
fmt.Printf("count = %d\n", count)
count--
}
numbers := [5]int{10, 20, 30, 40, 50}
for index, value := range numbers {
fmt.Printf("numbers[%d] = %d\n", index, value)
}

userAges := map[string]int{
"Alice": 25,
"Bob": 30,
"Charlie": 35,
}
// 遍历 map
for key, value := range userAges {
fmt.Printf("%s 的年龄是 %d\n", key, value)
}

str := "Hello, 世界"
// 遍历字符串的字符(rune)
for index, char := range str {
fmt.Printf("位置 %d: 字符 %c, Unicode: %U\n", index, char, char)
}
}

循环控制语句

break 和 continue

func main() {
// break 示例
fmt.Println("break 示例:")
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue // 跳过本次循环的剩余代码
}
if i == 8 {
break // 立即退出循环
}
fmt.Printf("%d ", i)
}
fmt.Println() // 输出: 1 3 5 7
}

带标签的 break 和 continue

func ForLoop(){
outerLoop:
for i := 0; i < 3; i++ {
fmt.Printf("外层循环 i=%d\n", i)

for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
fmt.Println("跳出外层循环")
break outerLoop // 跳出带标签的循环
}
fmt.Printf(" 内层循环 j=%d\n", j)
}
}
}

比较

type Person struct {
Name string
Age int
}
func main(){
p1 := Person{Name:"Bruce li",Age:18}
p2 := Person{Name:"Bruce li",Age:18}
fmt.Println("p1 == p2:", p1 == p2) // true 相同的内容,不同的指针
arr1 := [3]{54,55,56}
arr2 := [3]{54,55,56}
fmt.Println("arr1 == arr2:", arr1 == arr2) // true 相同的内容,不同的指针
// slice 不能用于比较
tasks := []string{"Task1", "Task2", "Task3"}
tasks2 := []string{"Task1", "Task2", "Task3"}
// fmt.Println("arr1 == arr2:", arr1 == arr2) // invalid operation: tasks == tasks2
// 和 nil 比较除外
fmt.Println(tasks == nil) // false
// struct 内部如果存在 slice 也不允许进行比较

// 如果是指针进行比较
pp1 := &Person{Name: "Bob", Age: 25}
pp2 := &Person{Name: "Bob", Age: 25}
pp3 := pp1
fmt.Println("pp1 == pp2:", pp1 == pp2) // false - 不同的实例
fmt.Println("pp1 == pp3:", pp1 == pp3) // true - 相同的实例
fmt.Println("*pp1 == *pp2:", *pp1 == *pp2) // true - 相同的值
}

defer

用于延迟方法的执行

func main() {
defer fmt.Println("World")
defer fmt.Println("Go")
fmt.Println("Hello")
}

// Output:
// Hello
// Go
// World
// 遵循后进先出原则(Last In First Out),栈

特殊符号

&

& 在变量左边:获取地址,& 在类型左边:指针类型

// 函数参数中的指针类型
func modifyPerson(p *Person) { // & 在 Person 左边,表示指针类型
p.Name = "修改后的名字"
}

// 返回值中的指针类型
func createPerson() *Person { // 返回 Person 的指针
return &Person{Name: "新创建"}
}

*

// 指针接收者方法
func (u *User) Activate() {
u.IsActive = true
}

错误捕获

// 让错误尽早的暴露,而不是不断地向上进行冒泡
const errorHandle = () => {
return {
err:true,
res:'出错了'
}
return {
err:false,
res:'需要的结果'
}
}

类型断言和 interface

参考文章

作者文章名称
峰华前端工程师https://www.bilibili.com/video/BV1HW4y1n7BF
从 js,转向go 语言https://prateeksurana.me/blog/guide-to-go-for-javascript-developers/