Go 语言



1. Golang开发

  1. 编译类型语言,速度快,可直接编译成机器码,可执行文件
  2. 部署简单,上传一个可执行文件
  3. 编译器和标准库、三方库都是Go语言实现
  4. 强类型语言
  5. 语言层面支持并发,轻松开发异步程序

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
posted @   linsonga  阅读(97)  评论(1编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示