go学习 模块与包 - Init函数 - 如何导入第三方包 - 切片与数组的数据传递方式 - go中文件的读写

目录

包(package)是组织和复用代码的基本单元。

包的种类:

包的导入

包的组成

如下两个文件中定义了A变量和 sc_num变量,他们的首字母开头分别为大写和小写,因此可以说明A变量是公有变量,而sc_num是私有变量。

go 风格指南

go中的Init函数

如何导入第三方包:

1、查看go的配置变量基本信息

2、开启GOMODULE管理方式(默认GO111MODULE=auto)

3、启用国内下载代理

4、创建go.mod文件

​编辑5、安装第三方包

go第三方安装包下载官网:Go Packages - Go Packages

6、导入实验代码

7、运行程序:

8、测试Web服务

如何在linux上运行该go语言Web服务器?

1、首先安装go语言环境

2、如果版本太低了,就需要卸载原来的go版本,安装新的go版本,而这则需要源码安装

3、源码安装go

4、部署Web服务

5、运行go语言程序

6、测试Web服务效果:

go的切片与数组(详细的数据传输解释)(go传递数据的时候使用的是传值的方式)

切片类型下数据的传递方式: 

数组类型下数据的传递方式:

什么是传值和传地址,他们的区别又是什么?

传值和传址的区别总结如下:

如何在go的函数中直接修改原数据的数组呢,而不是修改函数副本空间中的复制的数组呢?

如果输入数据超过切片的容量限制,会发生什么呢?

go的文件操作(文件的读写方式):

什么时候会用到go中的文件读写呀


包(package)是组织和复用代码的基本单元。

一个包可以包含多个Go源文件(以.go为扩展名),这些文件通常属于同一个功能或领域。每个源文件的开头都需要声明所属的包名。

包名 --》告知当前这个go文件属于哪个包(目录)

go文件 --》定义包中的内容(代码写在go文件中)

        --》main --》这是一个主运行文件

包的种类:

  1. 标准库包(Standard Library Packages):Go标准库提供了丰富的包来支持各种常见任务和功能,如字符串处理、文件操作、网络通信等。这些包无需额外安装,可以直接使用。(内置包:不需要安装、直接import导入即可使用)

  2. 第三方包(Third-Party Packages):Go社区拥有众多的第三方包,以满足各种特定需求。这些包通常由其他开发者或组织维护,并且需要使用工具如Go Modules或GOPATH来管理和导入。(第三方包:需要安装,再导入使用)

  3. 自定义包(Custom Packages):任何人都可以创建自己的Go包,并根据需要组织和导出函数、类型和变量。自定义包使代码更易于重用和维护。可以通过在代码文件的开头使用package关键字声明包名,并使用import语句在其他代码中导入自定义包。(自定义包:自己写的go包)

包的导入

// import "sc/user"      直接导入包的内容

// import u "sc/user"   导入之后取别名

// import _ "sc/user"   仅执行init函数中的内容

// import . "sc/user"    导入包中所有的内容

包的组成

一个目录表示一个包(sanchuang)、user子包
代码写到go文件中 => 

第一行声明当前文件属于当个包(建议包名与目录名同名)

同一个包下的文件,声明的包名应该一致
同一个包中,变量、函数等都是共享的(相互可见的)
文件中定义的对象 =》大写的标识符 表示Public , 小写的标识符表示Private

以大写字母开头的标识符(如变量名,函数名),都是表示Public

以小写字母开头的标识符,都是表示Private

如下两个文件中定义了A变量和 sc_num变量,他们的首字母开头分别为大写和小写,因此可以说明A变量是公有变量,而sc_num是私有变量。

 main文件

package main

// import 包名/子包名
// 取别名 => 有时候有些包的名字特别长.可以取别名
//u "sc/user"
// 仅仅执行sc/user包中的初始化信息
//_ "sc/user"
//. "sc/user"
// 注意事项:包名与目录名不一致,必须取一个别名 "sc/user" => 路径
//import (
//	"fmt"
//	"sc/user"
//)
import "fmt"
import u "sc/user"

func main(){
	fmt.Printf("start.....")
	//TeacherInfo()
	user.TeacherInfo()
	//u.TeacherInfo()
	//TeacherInfo()
	 变量,大写字母开头,小写字母开头
	 大写字母开头的变量,Public
	//fmt.Println(user.A)
	// 小写字母开头,私有的不能使用
	//fmt.Println(user.sc_num)
}

// init函数 => 初始化一些变量/数据的时候使用
func init(){
	fmt.Println("main init1")
}
func init(){
	fmt.Println("main init2")
}


go 风格指南

// 包名 => 小写+单数
// 文件名 => 小写+下划线
// 函数、结构体、接口、...:大驼峰 => UserName
// 变量名 => 小驼峰 => userName

go中的Init函数

init 函数是一种特殊的函数(初始化函数),它在程序运行时自动执行,而不需要显式调用。

init 函数有以下特点:

  • init 函数没有参数和返回值。
  • 一个包中可以定义多个init,一个文件中也可以定义多个init
  • 当一个程序运行时,首先会按照包的导入顺序初始化包级别的变量和常量。
  • 然后,在完成包级别的变量和常量初始化后,会按照导入顺序依次执行每个包中的 init 函数。
  • 如果一个包中有多个 init 函数,它们的执行顺序与定义顺序相同。
  • 当包被导入的时候init函数自动执行()

init 函数通常用于执行一些初始化操作,例如注册驱动、初始化全局变量、设置配置信息等。它可以提供程序运行前的一些准备工作。

下面是一个示例,展示了 init 函数的使用:

package main

import (
	"fmt"
)

var a int

func init() {
	fmt.Println("初始化 a 变量")
	a = 10
}

func main() {
	fmt.Println("main 函数执行")
	fmt.Println("a =", a)
}

在上面的例子中,init 函数用来初始化变量 a。当程序运行时,先执行 init 函数,然后再执行 main 函数。输出结果为:

初始化 a 变量 main 函数执行 a = 10

需要注意的是,init 函数在程序中只会执行一次,无论包被导入多少次。而且它不可以被其他函数调用或引用。

如何导入第三方包:

1、查看go的配置变量基本信息

go env --》查看go的配置变量信息

D:\衡山-开发\GO\Day_01\2023-07-21-go模块与包\sanchuang>go env
set GO111MODULE=auto         #用于控制Go Modules(模块)的行为
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\23843\AppData\Local\go-build
set GOENV=C:\Users\23843\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\23843\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\23843\go   #指定Go语言工作区的根目录,被用来指定存放Go源代码、编译后二进制文件和第三方包的位置。三方的依赖都安装到$GOPATH/pkg/mod目录下
set GOPRIVATE=
set GOPROXY=https://goproxy.cn,direct  #设置Go模块的代理服务器,默认情况下,Go模块会从官方的代理服务器 https://proxy.golang.org 下载模块的依赖包,但是我们需要修改为国内源,direct:直接从源地址下载依赖包,不通过代理服务器。
set GOROOT=E:\Go            #指定Go语言的安装路径,包含了Go语言的标准库和工具,$GOROOT\src:go的标准模块存储的地方
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=E:\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.19.2
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=D:\衡山-开发\GO\Day_01\2023-07-21-go模块与包\sanchuang\go.mod
set GOWORK=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=C:\Users\23843\AppData\Local\Temp\go-build3093873577
=/tmp/go-build -gno-record-gcc-switches

D:\衡山-开发\GO\Day_01\2023-07-21-go模块与包\sanchuang>

GO MODULES:是自Go 1.11版本引入的官方依赖管理工具,用于管理Go项目中的包版本和依赖关系。它解决了早期Go语言项目中对于第三方包的管理问题。

功能:依赖管理、版本选择、自动拉取、代理服务器支持、私有仓库支持

使用Go Modules的基本步骤如下:

  1. 初始化模块:在项目根目录下执行go mod init + 《项目名》命令,可以创建一个新的go.mod文件来初始化模块。

  2. 导入依赖包:通过import语句导入所需的依赖包。Go Modules会自动检测并下载缺失的依赖包。

  3. 构建和运行:使用go build命令构建项目,并使用go run命令运行项目。

  4. 管理依赖:可以使用go get命令来添加、更新或删除依赖包。Go Modules会自动更新go.mod文件和下载相应的包。

  5. 版本控制:可以在go.mod文件中指定所需的包版本,使用正确的语义版本控制规则。

因此我们创建的包中必须包含一个go.mod文件(下面的步骤都是在你的项目地址下进行的

D:\衡山-开发\GO\Day_01\2023-07-21-go模块与包\MyWeb

2、开启GOMODULE管理方式(默认GO111MODULE=auto)

go env -w GO111MODULE=on

3、启用国内下载代理

go env -w GOPROXY=https://goproxy.cn,direct

4、创建go.mod文件

go mod init web

5、安装第三方包

单个依赖安装
go get github.com/gin-gonic/gin
整体项目依赖的处理
go mod tidy

go第三方安装包下载官网:Go Packages - Go Packages

6、导入实验代码

package main

//server.go是主运行文件
import (
	"github.com/gin-gonic/gin"
	"net/http"
)
//gin是go中的一个Web框架

// 入口函数
func main(){
	// 创建一个web服务器
	r := gin.Default()

	// 当访问/sc => 返回{"message":"hello sanchang"}
	r.GET("/sc", func(c *gin.Context){
		// 200,
		c.JSON(http.StatusOK, gin.H{
			"message": "hello, sanchuang",
		})
	})

	// 运行web服务
	r.Run()
}

 

7、运行程序:

运行项目
go run server.go

8、测试Web服务

访问网址http://127.0.0.1:8080/sc

 

如何在linux上运行该go语言Web服务器?

1、首先安装go语言环境

[root@master ~]# yum install golang -y

2、如果版本太低了,就需要卸载原来的go版本,安装新的go版本,而这则需要源码安装

卸载软件

yum remove go -y

源码卸载:rm -rf /usr/local/go

3、源码安装go

首先找到go的安装包

路径:All releases - The Go Programming Language (google.cn)

我们需要安装go 1.19.11版本的安装包

wget https://golang.google.cn/dl/go1.19.11.linux-amd64.tar.gz

 解压安装包

[root@master ~]# tar -zxf go1.19.11.linux-amd64.tar.gz 

 配置环境变量

[root@master ~]# vim ~/.bashrc


#添加下面3条
GOROOT=/usr/local/go
export GOPATH=~/go
export PATH=$PATH:$GOPATH:$GOROOT/bin

#重新加载环境
[root@master ~]# source ~/.bashrc
[root@master ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/scnginx66/sbin:/usr/local/scnginx66/sbin:/root/go:/usr/local/go/bin

移动go程序到/usr/local/ 目录下,并查看go版本

[root@master ~]# mv go /usr/local/
[root@master ~]# ls /usr/local/go/bin
go  gofmt
[root@master ~]# go version
go version go1.19.11 linux/amd64
[root@master ~]# 

4、部署Web服务

首先创建server.go文件存放go语言Web程序

[root@master ~]# cd /
[root@master /]# mkdir myweb
[root@master /]# cd myweb/
[root@master myweb]# vim server.go
[root@master myweb]# ls
server.go
[root@master myweb]# cat server.go 
package main

//server.go是主运行文件
import (
	"github.com/gin-gonic/gin"
	"net/http"
)
//gin是go中的一个Web框架

// 入口函数
func main(){
	// 创建一个web服务器
	r := gin.Default()

	// 当访问/sc => 返回{"message":"hello sanchang"}
	r.GET("/sc", func(c *gin.Context){
		// 200,
		c.JSON(http.StatusOK, gin.H{
			"message": "hello, sanchuang",
		})
	})

	// 运行web服务
	r.Run()
}
[root@master myweb]# 

对go语言模块进行初始化(生成go.mod文件)

[root@master myweb]# go mod init web
go: creating new go.mod: module web
go: to add module requirements and sums:
	go mod tidy
[root@master myweb]# ls
go.mod  server.go
[root@master myweb]# 

下面对go语言模块进行加载

[root@master myweb]# go mod tidy

发现如下错误

[root@master myweb]# go mod tidy
go: finding module for package github.com/gin-gonic/gin
web imports
	github.com/gin-gonic/gin: module github.com/gin-gonic/gin: Get "https://proxy.golang.org/github.com/gin-gonic/gin/@v/list": dial tcp 172.217.160.113:443: i/o timeout
[root@master myweb]# 

是安装超时了,我们需要将它的源更改为国内源

[root@master myweb]# go env -w GO111MODULE=on
[root@master myweb]# go env -w GOPROXY=https://goproxy.cn,direct

安装成功:

[root@master myweb]# go mod tidy
go: finding module for package github.com/gin-gonic/gin
go: downloading github.com/gin-gonic/gin v1.9.1
go: found github.com/gin-gonic/gin in github.com/gin-gonic/gin v1.9.1
go: downloading github.com/gin-contrib/sse v0.1.0
go: downloading github.com/mattn/go-isatty v0.0.19
go: downloading golang.org/x/net v0.10.0
go: downloading github.com/stretchr/testify v1.8.3
go: downloading google.golang.org/protobuf v1.30.0
go: downloading github.com/go-playground/validator/v10 v10.14.0
go: downloading github.com/pelletier/go-toml/v2 v2.0.8
go: downloading github.com/ugorji/go/codec v1.2.11
go: downloading gopkg.in/yaml.v3 v3.0.1
go: downloading github.com/bytedance/sonic v1.9.1
go: downloading github.com/goccy/go-json v0.10.2
go: downloading github.com/json-iterator/go v1.1.12
go: downloading golang.org/x/sys v0.8.0
go: downloading github.com/davecgh/go-spew v1.1.1
go: downloading github.com/pmezard/go-difflib v1.0.0
go: downloading github.com/gabriel-vasile/mimetype v1.4.2
go: downloading github.com/go-playground/universal-translator v0.18.1
go: downloading github.com/leodido/go-urn v1.2.4
go: downloading golang.org/x/crypto v0.9.0
go: downloading golang.org/x/text v0.9.0
go: downloading github.com/go-playground/locales v0.14.1
go: downloading github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
go: downloading github.com/modern-go/reflect2 v1.0.2
go: downloading github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311
go: downloading golang.org/x/arch v0.3.0
go: downloading github.com/twitchyliquid64/golang-asm v0.15.1
go: downloading github.com/klauspost/cpuid/v2 v2.2.4
go: downloading github.com/go-playground/assert/v2 v2.2.0
go: downloading github.com/google/go-cmp v0.5.5
go: downloading gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
go: downloading golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
[root@master myweb]# 

5、运行go语言程序

[root@master myweb]# go run server.go 
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /sc                       --> main.main.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

6、测试Web服务效果:

go的切片与数组(详细的数据传输解释)(go传递数据的时候使用的是传值的方式)

package main

import "fmt"

// 切片是一种引用类型(存放的是地址)

func main(){
// 定义了一个切片 len 0, cap 10
var sli = make([]int, 0, 10)
fmt.Printf("原始sli:%v, %p, %p\n",sli, &sli, sli)
test(sli)
fmt.Printf("执行test后sli:%v\n",sli)
// sli[0:cap]
fmt.Printf("执行sli[:10]:%v\n",sli[:10])
}

func test(sli []int){
fmt.Printf("函数中sli:%v, %p, %p\n",sli, &sli, sli)
// 将切片追加数据
sli = append(sli,10,20,30)
fmt.Printf("函数中的结果是:%v\n",sli)
}

输出的结果是:

原始sli:[], 0xc000008078, 0xc00001e140
函数中sli:[], 0xc0000080c0, 0xc00001e140    #源sli和函数中的副本sli的地址是不一样的,但是里面的第一个数据的地址是一样的,说明go分配给切片的方式是传值(传递引用),这才会导致两个不同空间指向的数据中的地址都是一样的
函数中的结果是:[10 20 30]              #在test中运行,go分配空间给test函数中的sli使用
执行test后sli:[]         #test执行后,go收回分配给test函数的空间,导致不存在test中的sli切片了
执行sli[:10]:[10 20 30 0 0 0 0 0 0 0]    #原因是在test中他给副本的sli切片添加了数值,而副本的sli的数据的地址空间与源sli数据的地址空间是一样的,所以才导致源地址空间的sli切片的数据发生了改变


这里复制的是sli这个切片类型,在函数中复制的切片s发生了变化,外面的sl没有改变但是他们底层的数组发生了变化,数组没有被复制还是用的同一个吧
Process finished with exit code 0

切片类型下数据的传递方式: 

数组类型下数据的传递方式:

什么是传值和传地址,他们的区别又是什么?

传值(go语言):当使用传值方式将参数传递给函数时,函数会创建该参数的一个副本,并在函数内部使用该副本进行操作这意味着对参数进行的任何修改都只会影响到该副本,不会影响原始的参数。传值方式适用于简单的数据类型(如整数、浮点数、布尔值)或者在函数内部不需要修改原始参数的情况。

传地址(python语言):当使用传地址方式将参数传递给函数时,实际上是将参数的内存地址传递给函数。这样,在函数内部可以直接访问和修改原始参数的值。因为是直接操作原始参数,所以对参数的修改会影响到原始参数的值。传地址方式适用于复杂的数据类型(如数组、切片、映射、结构体)或者需要在函数内部修改原始参数的情况。

传值和传址的区别总结如下:

  1. 传值是将参数的副本传递给函数,对副本的任何修改都不会影响原始参数。
  2. 传地址是将参数的内存地址传递给函数,允许直接访问和修改原始参数。
  3. 传值适用于简单的数据类型或者不需要修改原始参数的情况。
  4. 传地址适用于复杂的数据类型或者需要在函数内部修改原始参数的情况。

如何在go的函数中直接修改原数据的数组呢,而不是修改函数副本空间中的复制的数组呢?

go语言中,当调用一个函数的时候,函数的每个调用参数将会被赋值给函数内部的参数变量,所以函数参数变量接收的是一个复制的副本,并不是原始调用的变量。
因为函数参数传递的机制导致传递大的数组类型将是低效的,并且对数组参数的任何的修改都是发生在复制的数组上,并不能直接修改调用时原始的数组变量。
我们可以显式地传入一个数组指针,那样的话函数通过指针对数组的任何修改都可以直接反馈到调用者。

如果输入数据超过切片的容量限制,会发生什么呢?

定义了一个切片(slice)变量 sli,长度为 0,容量为 3,如果输入数据超过容量限制,会直接创建一个新的底层数组 

因为我们定义的切片只有3个容量,但是我们需要输入4个容量的数据,因此函数中的sli切片会定义另外一个底层数组用来存储数据(与源地址空间的sli切片的底层数组不同),这导致源地址空间的sli切片的底层数组并没有存储数据,而数据是保存在了函数中副本空间内的sli切片定义的新的底层数组空间中。

go的文件操作(文件的读写方式):

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main()  {
	// 获取当前路径,防止创建文件的时候不知道文件被创建的路径在哪里
	wd, err := os.Getwd()
	if err != nil{                  //异常处理
		fmt.Println("获取当前路径失败", err)
	}
	fmt.Println("当前路径为:", wd)
	// 在当前目录
	filePath := "./golang.txt"

	file,err := os.OpenFile(filePath,os.O_CREATE|os.O_WRONLY, 0666)
	// go对于错误的错误权交给了用户
	if err!=nil{                    //异常处理
		fmt.Println("打开文件失败", err)
		return
	}
	// 如果打开文件没有出错
	// defer延迟执行(如果程序遇到panic也会执行)
	defer file.Close()                //异常处理

	//写入数据
	write := bufio.NewWriter(file)
	for i:=0;i<5;i++{
		write.WriteString("hello sc!\n")
	}
	//因为我们写入的数据是在缓存中,我们需要写道磁盘中,因此需要对数据进行一个强刷,将数据保存到磁盘(文件)当中
	write.Flush()
}

结果为:

什么时候会用到go中的文件读写呀

爬虫(图片、文件)

写日志 --》 日志模块

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值