GO 语言入门
语法基础
定义
1.批量格式
var a,b int
var a int = 114514
var (
a int
b string
c []float32
)
type ST struct{
x int
y int
}
i,j:=0,1 // 定义在func内才行
const e_pi = 3.14 //芝士常量
注: _ 为匿名变量。
提供一些 go 的基本类型吧:
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // uint8 的别名
rune // int32 的别名
// 表示一个 Unicode 码点
float32 float64
complex64 complex128
(硬(en)抄的)
以及一些占位符
%v:通用占位符,根据值的类型进行格式化输出。
%d:十进制整数。
%b:二进制表示的整数。
%o:八进制表示的整数。
%x:十六进制表示的整数(使用小写字母 a-f)。
%X:十六进制表示的整数(使用大写字母 A-F)。
%f:浮点数(默认精度为小数点后六位)。
%e、%E:科学计数法表示的浮点数。
%s:字符串。
%t:布尔值(true 或 false)。
%p:指针的十六进制表示。
%c:字符(Unicode码点值)。
%U:Unicode格式:U+1234。
%%:百分号自身(无操作数)。
(gpt)
import
重要但简单的一环,类似 py,可以写在一堆:
import (
"fmt"
"math"
)
注意,在go中,左括号什么的不允许换行(震怒)
引用时注意,首字母大写才说明来自某个包,比如:
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.Pi)
}
如果是
math.pi
就会寄。
函数
在 go 中,定义都是放在后面的,函数也不例外。
比如:
package main
import "fmt"
func add(x int, y int) int {
return x + y
}
func main() {
fmt.Println(add(42, 13))
}
后缀的type如果不写就是void
package main
import "fmt"
var c int
func add(x int, y int) {
c = x + y
}
func main() {
add(23, 4)
fmt.Println(c)
}
不 return 的话可以直接
return
(真的是 c Pro MAX)
1当然,如果多写就是返回多个(这点很灵活)
一个例子
package main
import "fmt"
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := "1!", "5!"
fmt.Println(a, b)
fmt.Println(swap(a, b))
}
轻松实现了swap
在声明参数的时候,可以合并同类项
func add(x,y int) int {
循环
牛魔的go,大括号不提行就算了,nm怎么连 for 的括号都不打
几乎与 c 一样
for i:=0; i < n ;i++{
}
for 也可以当成 while 用
for sum <1000 {
sum +=sum
}
注:可以直接
for {
}
来玩无限循环
分支
我发现 go 真的不喜欢打 (),真的很喜欢 {}
所以 if 就是 c 的不打小括号版本,同时不允许不写 {}
懒得写例子了。
切片
与python差不多
注意,是 左闭右开 的
同时,切片就像指针一样,修改会影响原本的。
一个相当不错的例子
package main
import "fmt"
func main() {
names := [4]string{
"John",
"Paul",
"George",
"Ringo",
}
fmt.Println(names)
a := names[0:2]
b := names[1:3]
fmt.Println(a, b)
b[0] = "XXX"
fmt.Println(a, b)
fmt.Println(names)
}
output
[John Paul George Ringo]
[John Paul] [Paul George]
[John XXX] [XXX George]
[John XXX George Ringo]
指针
指针是Go语言中一个重要的概念,用于存储变量的内存地址。通过指针,可以直接访问和修改变量的值,而无需拷贝数据,从而提高程序的效率。与其他语言不同,Go语言不支持指针运算,这减少了内存错误的风险。
当我们将一个变量的地址赋值给一个指针时,指针就指向了该变量的内存地址。这样,我们可以通过指针来读取或修改变量的值。这在需要在函数中修改参数的值或需要共享大型数据结构时非常有用。
结构体
结构体(struct)是Go语言中用于定义自定义数据类型的方式。它将一组具有不同类型的数据组合在一起,形成一个整体。结构体在组织复杂的数据结构时非常有用。
通过结构体,我们可以模拟现实世界中的实体,将其属性和行为进行封装。结构体的字段可以是基本类型、指针、甚至是其他结构体。这样,我们可以构建出复杂的数据模型,提高代码的可读性和维护性。
方法
方法是与特定类型关联的函数。在Go语言中,我们可以为结构体类型定义方法,这使得我们可以为自定义类型添加行为。
方法的接收者可以是值类型或指针类型。使用值类型作为接收者时,方法接收的是类型的副本,无法修改原始数据。使用指针类型作为接收者时,方法可以直接修改原始数据。这种设计提供了灵活性,允许我们根据需要选择合适的接收者类型。
通过为结构体定义方法,我们可以实现面向对象编程中的封装和数据隐藏,使代码结构更加清晰。
接口
接口是Go语言中实现多态和抽象的关键机制。它定义了一组方法的集合,任何实现了这些方法的类型都被视为实现了该接口。
接口的使用使得代码更加灵活和可扩展。我们可以编写函数或方法,接受接口类型作为参数,从而支持多种不同的具体类型。这种设计模式在大型项目中尤为重要,有助于降低耦合度,提升代码的可维护性。
例如,定义一个Animal接口,包含一个Speak方法。任何实现了Speak方法的类型都可以被视为Animal类型。这使得我们可以编写通用的代码,处理不同的动物类型,而无需关心其具体实现。
package main
import "fmt"
type Animal interface {
Speak() string
}
type Dog struct{}
type Cat struct{}
func (d Dog) Speak() string {
return "Woof!"
}
func (c Cat) Speak() string {
return "Meow!"
}
func main() {
animals := []Animal{Dog{}, Cat{}}
for _, animal := range animals {
fmt.Println(animal.Speak())
}
}
并发编程
Go语言的一个显著特性是对并发的支持。它通过协程(goroutine)和通道(channel)提供了强大的并发编程能力。
协程(goroutine)
协程是由Go运行时管理的轻量级线程。与传统的线程相比,协程的创建和销毁成本非常低,因此可以在程序中创建大量的协程来处理并发任务。
使用关键字go可以启动一个新的协程。例如,go functionName()将会在新的协程中异步执行functionName函数。这使得编写并发程序变得简单直观,无需处理复杂的线程管理和同步问题。
通道(channel)
通道用于在不同的协程之间传递数据。它是类型安全的,可以避免数据竞争问题。
通过通道,我们可以实现协程之间的通信和同步。发送操作和接收操作都是阻塞的,直到另一端准备好。这种机制简化了并发程序的设计,减少了使用锁和共享内存的复杂性。
例如,在生产者-消费者模式中,生产者协程可以将数据发送到通道中,消费者协程从通道中接收数据,从而实现数据的安全传递。
JSON处理
在现代应用中,JSON是一种常用的数据交换格式。Go语言的encoding/json标准库提供了对JSON数据的编码和解码支持。
通过定义结构体并添加适当的标签(tags),我们可以轻松地将Go语言的结构体与JSON数据进行映射。这使得处理JSON数据变得简单而直观。
在序列化时,我们可以使用json.Marshal()函数将结构体转换为JSON格式的字节数组。反序列化时,可以使用json.Unmarshal()函数将JSON数据解析为结构体。