Go 语言
1. Golang开发
- 编译类型语言,速度快,可直接编译成机器码,可执行文件
- 部署简单,上传一个可执行文件
- 编译器和标准库、三方库都是Go语言实现
- 强类型语言
- 语言层面支持并发,轻松开发异步程序
2. 与php开发环境对比
3. 打印变量常用动词及功能
fmt.Print() // 打印变量
fmt.Println() // 换行打印
fmt.Printf() // 格式化输出 如:a = 1; fmt.Printf("%d", a)
动词 | 功能 |
---|---|
%T | 返回变量类型和值 |
%f | 浮点类型 如:保留两位小数 a = 3.1415; fmt.Printf("%.2f", a) 同时进行4舍5入 |
%t | 布尔类型 |
%c | 字符 |
%s | 字符串 |
%v | 按值的本来值输出 |
%+v | 在 %v 基础上,对结构体字段名和值进行展开 |
%#v | 返回变量值 |
%b | 整型,二进制显示 |
%o | 整型,八进制显示 |
%d | 整形,十进制展示 |
%x | 整形,十六进制展示 |
%X | 整型,十六进制、字母大写方式显示 |
%p | 指针,十六进制显示 |
%U | Unicode 字符 |
4. 已有函数
strings.Count(str, val) // 统计字符串中字符出现的次数 str字符串 val匹配的值
len (str) // 获取字符串长度
append(arr, "123") // 向切片,数组尾部添加元素
5. 变量
变量的类型很重要,因为这决定了可将什么值赋给该变量。
如对类型为string的变量,不能将整数赋值给它。将不匹配的值赋值给变量时,将导致编译错误。
// 使用 var 声明变量
var age int = 10
// 可以先声明类型,在赋值。未赋值的变量为该类型的零值
var str string
str = "Hello World"
// 多个变量相同类型
var s1, s2 string = "S1", "S2"
// 自动推导类型
num := 10
// 变量交换
age := 10
sex := 10
age,sex = sex,age
// 变量作用域,指变量可以在什么地方使用,而不是说变量在哪里声明的
// 块内可以访问块外的变量,块外不能访问块内变量
func main() {
var s1 = "s1"
{
var s2 = "s2"
// 可以访问s1,s2
fmt.Println(s1, s2)
{
var s3 = "s3"
// 可以访问s1,s2,s3
fmt.Println(s1, s2, s3)
}
}
// 只能访问s1
fmt.Println(s1)
}
// 单字符用单引号
var a byte = 'A'
// 字符串用双引号
str := "abcde"
// 布尔类型,,零值为false
var b bool
// 类型转换
a := 3.14
fmt.Println(int(a))
// 常量
const PI float64 = 3.14 // 常量定义使用const,变量名字一般大写
6. 指针
// 以 php 为例php 传值,相当于复制
$a = 1;
$b = 2;
$b = $a; // a 赋值给 b
echo $b; // 为1
// 引用赋值
$a = 1;
$b = &$a; // 将 $a 引用传给 $b
echo $a; // 为1
$b = 2; // 把 $b 赋值为 2
echo $a; // 显示为2
Go 语言中 只有值传递 一种方式,用指针代替引用方式
// Go语言例子1
func swap(a, b *int) {
*b, *a = *a, *b
}
a, b := 3, 4
swap(&a, &b)
fmt.Println(a, b)
// 列子2
func swap(a, b int) (int, int) {
return b, a
}
a, b := 3, 4
a, b = swap(a, b)
fmt.Println(a, b)
7. 数组
var arr [4]int // 不赋值默认为 0,开辟了4个空间使用容量
arr1 := [3]int{2, 7, 9}
arr2 := [...]int{4, 10, 28} // 用...编译器根据数值自动获取数量
var arr3 [2][3]bool // 声明二维数组,2行 3列 [[0, 0, 0] [0, 0, 0]]
// 类型右边是数值,左边是空间容量
// 循环数组
for i:=0; i<= len(arr); i++ {
fmt.Println(i);
fmt.Println(arr[i])
}
// 使用 range 关键字循环
for i, v := range arr{
fmt.Println(arr[i])
fmt.Println(arr[v])
}
// [10]int和[20]int是不同类型
// 调用func f(arr [10]int) 会拷贝数组
8. 切片 slice
切片可以扩容,而数组是固定大小
// 创建
var stack []string
// 赋值
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
res1 := arr[2:6] // [2, 3, 4, 5] [数值, 数值减1]
res2 := arr[:4] // [0, 1, 2, 3]
res3 := arr[3:] // [3, 4, 5, 6, 7, 8]
res4 := arr[:] // 获取所有
// slice 扩展
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6] // [2, 3, 4, 5]
s2 := s1[3:5] // [5, 6] 为什么是5, 6
clice扩展
- 底层数值为 [0, 1, 2, 3, 4, 5, 6, 7]
- s1 的值为 [2, 3, 4, 5],slice会扩展之后的值[6, 7]。s1[4],s1[5] 不会显示对应的值
- 当 s2 超过 s1 的值时,会获取 s1 扩展的内容
slice内部实现
- slice 内部包含 prt开头元素,len长度,cap扩展长度
- 可以向后扩展,不可以向前扩展
- s1[i] 不可以超越 len(s1),向后扩展不可以超越cap(s)
fmt.Println(len(s1)) // 数值值长度 4
fmt.Println(cap(s1)) // 扩展长度 8
// 添加
arr := [...]int{0, 1, 2, 3, 4, 5}
s2 := append(arr, 100)
append会新创建一个数组,向末尾数组增加元素,cap会自动扩充,条件是乘以 2
// 使用make创建制定大小的变量,创建方式
// make ([]type, len, cap),type数组元素类型,len长度,cap容量
arr1 := make([]int, 2, 8)
arr2 := make([][2]int, 3, 100) // 二维数组切片
// 拷贝
arr := []int{1, 2, 3, 4, 5}
arr2 := make([]int, 10, 100)
copy(arr2, arr)
9. make
make用于内存分配,和new不同,它只用于通道chanl、映射map、切片slice的内存创建
- 用于灵活地创建切片
- 创建方式 make ([]type, len, cap),type数组元素类型,len长度,cap容量
//创建一个初始元素长度为5的数组切片,元素初始值为0:
mySlice1 := make([]int, 5)
//创建一个初始元素长度为5的数组切片,元素初始值为0,并预留10个元素的存储空间:
mySlice2 := make([]int, 5, 10)
//切片字面量创建长度为5容量为5的切片,需要注意的是 [ ] 里面不要写数组的容量,因为如果写了个数以后就是数组了,而不是切片了。
mySlice3 := []int{10, 20, 30, 40, 50}
10. range循环
func numHandel(num...int) int { // ...获取多个参数, int返回函数类型
var a int
for k,v := range num { // 赋值给 k,v . 不想用k,k可以用_代替(匿名变量:不会保存具体数据)
fmt.Println(v)
a += v
}
return a
}
func main(){
var b int
b = numHandel(2, 5, 10, 76);
fmt.Println(b)
}
11. map
// 创建一个 map
var arr map[string]string // arr = nil
arr2 := map[string]string{
"name":"张三",
"sex" : "男",
}
// 使用 make
arr3 := make(map[string]string) // empty map
// 循环 map
for _, v := range arr2 {
fmt.Println(v)
}
// 获取 map 中的内容
value := arr2["name"]
value2:= arr2["haha"] // map不存在的key返回空
// 判断 map 中的 key 是否存在
if value3, ok := arr2["fufei"] ; ok{
fmt.Println(value3)
}else{
fmt.Println("参数不存在")
}
name, ok := arr2["name"] //
fmt.Println(name, ok)
// 删除 map 中某个 key
delete(arr2, "name")
name, ok = arr2["name"] // 这里使用 = 等号,因为前面已经赋过值
fmt.Println(name, ok)
12. 结构和方法
go 语言中没有类的概念,但是可以通过结构体 struct 实现 oop (面向对象编程)
围绕具体细节构建抽象,是编程语言可以提供给开发人员的最大工具
结构可以让代码更适当地使用数据,可以以多种不同的方式定义和使用结构
结构的工作方式类似于纸质表格。包含你的名字、性别和年龄,结构将不同的数据收集在一起,当您使用新的结构体初始化变量时,就好像您已经将表格准备好填写一样。
package main
import "fmt"
// 定义树形结构体
// 结构内 变量名在前,结构在后
type treeNode struct {
value int
left, right *treeNode // 使用指针
}
// 值接收,对值的拷贝,不能改变内容
// 语法写法不同,参数在前面,方法名字在后面
func (node treeNode) print() {
fmt.Print(node.value, "\n")
}
// 指针接收,改变值内容
func (node *treeNode) setValue(value int) {
node.value = value
}
// 遍历结构
func (node *treeNode) traveres(){
if node == nil {
return
}
// 使用中序遍历,先遍历每个数的左边在遍历每个数的右边
node.left.traveres()
node.print()
node.right.traveres()
}
func main() {
// 1. 创建结构
var tree treeNode // 创建结构
tree = treeNode{value:1} // 创建value10
//tree.left = &treeNode{} // left为指针,要取地址符
//tree.right = new(treeNode) // new 为内建函数,内容同上
tree.left = &treeNode{value:3}
tree.right = &treeNode{value:10}
// 2. 结构内容重新复制,展示结构
tree.setValue(100)
tree.print()
// 3. 遍历结构
tree.traveres()
}
13. 接口
// main.go
package main
import (
"awesomeProject1/retriever/mock"
"fmt"
)
// 定义接口结构体
type Retriever interface {
Get(url string) string
}
// download方法传递参数
func download(str Retriever) string {
return str.Get("http://www.imooc.com/") // 调用 mockretriever get 方法
}
func main() {
fmt.Println(download(mock.Retriever{}))
}
// mockretriever.go
package mock
import (
"net/http"
"net/http/httputil"
)
type Retriever struct {
}
// get方法 具体实现 Retriever
func (r Retriever) Get(url string) string {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
result, err := httputil.DumpResponse(resp, true)
resp.Body.Close()
if err != nil {
panic(err)
}
return string(result)
}
14. 闭包
package main
import "fmt"
type iAdder func(int) (int, iAdder)
func adder2(base int) iAdder {
return func (v int) (int, iAdder) {
return base + v, adder2(base + v)
}
}
func main() {
a := adder2(0)
for i:=0; i<=10; i++ {
var s int
s, a = a(i)
fmt.Println(i, s)
}
}
15. defer
defer延迟调用
- 在函数结束时调用
- defer 列表为先进后出
- 参数在 defer 语句时计算
package main
import "fmt"
func main() {
fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println(4)
}
// 1 4 3 2
16. math 包
i := -100
math.Abs(float64(i)) //绝对值
math.Ceil(5.0) //向上取整
math.Floor(5.8) //向下取整
math.Mod(11, 3) //取余数,同11%3
math.Modf(5.26) //取整数,取小数
math.Pow(3, 2) //x的y次方
math.Pow10(4) // 10的n次方
math.Sqrt(8) //开平方
math.Cbrt(8) //开立方
math.Pi // 兀
17. 标准库 ioutil
ioutil.ReadAll // 遍历增加函数内部buf容量并读取,直到把内容全部读到buf中
ioutil.ReadFile // 调用readall方法直接全部读取文件内容
ioutil.WriteFile // 写内容到文件,如果文件不存在则新建,如果存在则清空再写
ioutil.ReadDir // 获取指定文件地址下面文件的信息
ioutil.TempFile // 生成文件夹
ioutil.TempDir // 生成文件夹,返回名字
18. 错误
1. package **** is not in GOROOT (***)
// 在项目的当前目录里,执行命令:go mod init ,会在当前项目目录下自动创建go.mod文件
2. go-error-启动错误-open usrlocalgopkgdarwin_amd64runtimecgo.a: permission denied
// 取消掉go build -i
// GOland编辑器中 run->Edit Configurations->Go tool arguments 取消-i
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律