Go语言环境配置
安装:
Downloads - The Go Programming Language
配置环境变量,命令行运行go检查是否安装成功.
C:\Users\Mek>go
Go is a tool for managing Go source code.
Usage:
go <command> [arguments]
The commands are:
bug start a bug report
build compile packages and dependencies
clean remove object files and cached files
doc show documentation for package or symbol
env print Go environment information
fix update packages to use new APIs
fmt gofmt (reformat) package sources
generate generate Go files by processing source
get add dependencies to current module and install them
install compile and install packages and dependencies
list list packages or modules
mod module maintenance
work workspace maintenance
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet report likely mistakes in packages
Use "go help <command>" for more information about a command.
Additional help topics:
buildconstraint build constraints
buildmode build modes
c calling between Go and C
cache build and test caching
environment environment variables
filetype file types
go.mod the go.mod file
gopath GOPATH environment variable
gopath-get legacy GOPATH go get
goproxy module proxy protocol
importpath import path syntax
modules modules, module versions, and more
module-get module-aware go get
module-auth module authentication using go.sum
packages package lists and patterns
private configuration for downloading non-public code
testflag testing flags
testfunc testing functions
vcs controlling version control with GOVCS
Use "go help <topic>" for more information about that topic.
#设置环境参数
set GO111MODULE=on
set GOPROXY=http://goproxy.cn
//使IDE里软件源生效
go env -w GOPROXY=https://goproxy.cn,direct
#查看环境参数
go env
set GO111MODULE=on
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\Mek\AppData\Local\go-build
set GOENV=C:\Users\Mek\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\Mek\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\Mek\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=http://goproxy.cn
set GOTMPDIR=
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.18.3
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=NUL
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 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\Mek\AppData\Local\Temp\go-build3671658861=/tmp/go-build -gno-record-gcc-switches
Go 可用命令
#可以直接在终端里输入go或者go help 查看可用命令
#常用命令翻译
go build <gofile> --编译包
go run <gofile> --运行y
go clean --编译后移除对象文件
go doc --显示包或者符号文档
go env --打印环境信息
go fmt <gofile> --对代码进行格式化
go get <packname> --下载依赖包
ge install --编译并安装依赖包
代码编码规范
#包名小写
package main
package mektool
#变量小驼峰
var nameTel string
#常量大写_分割单词
URL = "www.mek.plus"
#文件名用_分割单词
mek_tool.go
mysql_model.go
#结构体驼峰命名法
type MysqlClose()
#接口类型用er结束
type Queryrer()
编写Go代码
1.Hello Go!
package main //主程序包名必须为main,主函数名必须为main,用双斜线表示注释
import "fmt" //导入fmt包
func main() { //主函数,程序开始运行的地方
fmt.Println("Hello Go!")
}
2.导入包
//定义包
//#MekTool/MekTool.go 文件在项目下的路径
package MekTool //声明包名
func Mek() string { //定义函数,返回一个字符串
return "Mek" //返回一个"Mek"
}
//使用包
//#main.go
package main
import ( //导入包
"StartGO/MekTool"
"fmt"
)
func main() {
s := MekTool.Mek() //将函数赋值给s
fmt.Println("OK!")
println(s) //打印s
}
3.声明变量 *Go语言里函数内的变量必须使用,否则不能通过编译
package main
import "fmt"
//声明变量 产量和函数
//全局变量声明
var tite string = "100" //声明并赋值
var vis string //声明不赋值
//声明全局常量
const URL = "mek.plus"
const URL2 string = "mek.plus"
//批量声明变量
var (
s1 string
s2 int
s3 bool
s4 float32
)
func Go() { //声明函数
vis = "Go2" //函数内给全局变量赋值
//批量赋值
s1, s2, s3, s4 = "ok", 16, true, 3.14
println("Go", vis)
fmt.Println(s1, s2, s3, s4)
}
//声明函数并返回两个匿名变量
func getNameArg() (string, int) {
return "Mek", 18
}
//声明一个函数返回两个具名变量
func getNameArg2() (name string, arg int) {
name = "Mek"
arg = 18
return name, arg
}
func printName() {
name, arg := getNameArg() //接收函数返回的变量
println(name,arg)
name2, _ := getNameArg2() //使用_ 舍弃返回的另一个变量
println(name2)
}
func main() {
Go() //调用函数
printName()
vis = "Go Go Go"
//局部普通声明,var关键字+变量名+类型
var name string
var arg int
var sex bool
//变量初始化
name = "Mek"
arg = 16
sex = false
//函数内快速声明变量
text := "Go!"
money := 1024
println(name, arg, sex, text, money, tite, vis)
}
4.数据类型和字符串操作
package main
import (
"bytes"
"fmt"
"strings"
)
//数据类型
func main() {
name := "Mek"
age := 20
//可以通过 Printf %T 打印数据类型
fmt.Printf("%T \n", name)
fmt.Printf("%T \n", age)
//指针类型,将p指向age
p := &age
fmt.Printf("%T \n", p)
//数组 数组名称 :=[长度]类型{值}
a_list := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
fmt.Printf("%T \n", a_list)
fmt.Printf("", a_list)
//切片,没有固定长度
b_list := []int{10, 20, 30}
fmt.Printf("\n", b_list)
//字符串
var s0 string = "S0"
var s1 = "S1"
s2 := "S2"
//反引号表示多行字符串
s3 :=
`
n1
n2
n3
`
//字符串并接
s4 := s3 + s2
s5 := fmt.Sprintf("%s,%s", s2, s0) //使用fmt内置函数格式化字符串,返回一个变量
var buffer bytes.Buffer //使用Buffer 并接字符串
buffer.WriteString("Hello")
buffer.WriteString(",")
buffer.WriteString("Go!")
mag := buffer.String() //调用String()函数把写入的字符串赋值给mag
println(mag)
//字符串截取
srt11 := "Hello Go!"
println(srt11[0:6]) //从开始截取到6-1
println(srt11[0:]) //从开始到结尾
println(len(srt11)) //获取字符串长度
//字符串操作 String 包含很多字符串操作函数
println(strings.ToLower(srt11)) //转换为小写
println(strings.ToUpper(srt11)) //转换为大写
println(strings.Contains(srt11, "Go")) //是否包含
println(strings.Index(srt11, "Go")) //获取索引位置
println(strings.Replace(srt11, "Go", "Python",1)) //替换
println(strings.HasPrefix(srt11, "He")) //是否什么开头
println(strings.HasSuffix(srt11, "Go!")) //是否什么结尾
fmt.Println("\n", s0, s1, s2, s3, s4, s5)
}
5.格式化输出
%v 按值的本来值输出
%+v 在 %v 基础上,对结构体字段名和值进行展开
%#v 输出 Go 语言语法格式的值
%T 输出 Go 语言语法格式的类型和值
%% 输出 % 本体
%b 整型以二进制方式显示
%o 整型以八进制方式显示
%d 整型以十进制方式显示
%x 整型以十六进制方式显示
%X 整型以十六进制、字母大写方式显示
%U Unicode 字符
%f 浮点数
%p 指针,十六进制方式显示
//main.go
package main
import (
"fmt"
"os"
)
type point struct {
x, y int
}
func main() {
p := point{1, 2}
fmt.Printf("%v\n", p)
fmt.Printf("%+v\n", p)
fmt.Printf("%#v\n", p)
fmt.Printf("%T\n", p)
fmt.Printf("%t\n", true)
fmt.Printf("%d\n", 123)
fmt.Printf("%b\n", 14)
fmt.Printf("%c\n", 33)
fmt.Printf("%x\n", 456)
fmt.Printf("%f\n", 78.9)
fmt.Printf("%e\n", 123400000.0)
fmt.Printf("%E\n", 123400000.0)
fmt.Printf("%s\n", "\"string\"")
fmt.Printf("%q\n", "\"string\"")
fmt.Printf("%x\n", "hex this")
fmt.Printf("%p\n", &p)
fmt.Printf("|%6d|%6d|\n", 12, 345)
fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
fmt.Printf("|%6s|%6s|\n", "foo", "b")
fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
s := fmt.Sprintf("a %s", "string")
fmt.Println(s)
fmt.Fprintf(os.Stderr, "an %s\n", "error")
}
//输出
bash#: go run main.go
{1 2}
{x:1 y:2}
main.point{x:1, y:2}
main.point
true
123
1110
!
1c8
78.900000
1.234000e+08
1.234000E+08
"string"
"\"string\""
6865782074686973
0xc0000b4010
| 12| 345|
| 1.20| 3.45|
|1.20 |3.45 |
| foo| b|
|foo |b |
a string
an error
6.运算符
package main
import "fmt"
//运算符
func main() {
var a int = 21
var b int = 10
var c int
//加减乘除运算
c = a + b
fmt.Printf("第一行 - c 的值为 %d\n", c )
c = a - b
fmt.Printf("第二行 - c 的值为 %d\n", c )
c = a * b
fmt.Printf("第三行 - c 的值为 %d\n", c )
c = a / b
fmt.Printf("第四行 - c 的值为 %d\n", c )
c = a % b
fmt.Printf("第五行 - c 的值为 %d\n", c )
a++ //自加1
fmt.Printf("第六行 - a 的值为 %d\n", a )
a=21 // 为了方便测试,a 这里重新赋值为 21
a-- //自减1
fmt.Printf("第七行 - a 的值为 %d\n", a )
//判断运算
if( a == b ) {
fmt.Printf("第一行 - a 等于 b\n" )
} else {
fmt.Printf("第一行 - a 不等于 b\n" )
}
if ( a < b ) {
fmt.Printf("第二行 - a 小于 b\n" )
} else {
fmt.Printf("第二行 - a 不小于 b\n" )
}
if ( a > b ) {
fmt.Printf("第三行 - a 大于 b\n" )
} else {
fmt.Printf("第三行 - a 不大于 b\n" )
}
/* Lets change value of a and b */
a = 5
b = 20
if ( a <= b ) {
fmt.Printf("第四行 - a 小于等于 b\n" )
}
if ( b >= a ) {
fmt.Printf("第五行 - b 大于等于 a\n" )
}
//与或运算
var a1 bool = true
var b1 bool = false
if ( a1 && b1 ) {
fmt.Printf("第一行 - 条件为 true\n" )
}
if ( a1 || b1 ) {
fmt.Printf("第二行 - 条件为 true\n" )
}
/* 修改 a 和 b 的值 */
a1 = false
b1 = true
if ( a1 && b1 ) {
fmt.Printf("第三行 - 条件为 true\n" )
} else {
fmt.Printf("第三行 - 条件为 false\n" )
}
if ( !(a1 && b1) ) {
fmt.Printf("第四行 - 条件为 true\n" )
}
}
7.流程控制语句
package main
//条件控制语句
// goto -- 跳转到某个标签
// fallthrough -- switch语句穿透
// break -- 退出当前for循环,只能退出一个for循环
// continue -- 开始结束当前if判断
func 循环控制() {
a := 90
//if 语句
if a < 100 { //if 语句控制
println("a<100")
} else if a < 50 {
println("a<50")
} else {
println("a>100")
}
//switch 语句
switch a { //switch 语句控制
case 49:
println("49")
fallthrough //fallthrough穿透语句,执行完这行顺带执行下一行
case 100:
println("100")
default: //default 默认选择
println(a)
}
day := 8
switch day {
case 1, 2, 3, 4, 5:
println("今天要上班!")
case 6, 7:
println("今天不上班!")
case 8:
println("哪有什么星期八?")
fallthrough //穿透到下一行
default:
println("非法输入!", day)
}
/*for循环 结构体 for 初始语句;条件表达式;结束语句{
循环体 } */
for i := 1; i <= 10; i++ {
println(i)
}
i1 := 1 //可以把初始条件写到外面
for i1 <= 10 {
println(i1)
i1++
}
for { //一直循环
println("run.....", i1)
i1++
}
}
func 进阶for循环() {
var a = [...]int{2, 4, 6, 8, 10, 12, 14, 16, 18} //定义一个数组
println(len(a)) //打印数组长度
//使用for循环该数组
for i, v := range a { //使用for循环该数组,i表示索引,v表示值
println(i, v)
}
for _, v := range a { //不接收索引只接收值
println(v)
}
for i := 1; i <= 10; i++ {
println(i)
if i == 5 { //i=5 时跳出for循环
break
}
}
}
func testGoto() {
//goto 用于跳转程序到某个标签
a := 2
if a == 1 { //在if中使用
println("a=1")
} else {
goto END
}
FOR:
for a <= 10 { //在if中使用用于跳出双循环
println(a)
for c := 1; c <= 10; c++ {
println(a,c)
if a == 5 && c == 5 {
goto END
}
}
a++
}
END:
a = 1
println("END")
goto FOR
}
func main() {
testGoto()
}
8.数据结构
数组 类似python的元组,可访问修改不可增删
package main
import "fmt"
//数组
func test1() {
//定义数组 var 数组名称 [长度] 数组类型
var a1 [3]int //定义一个长度为3的int类型数组
var a2 [3]string // 定义一个长度为3的字符串类型数组
a_list := [8]int{1, 2, 3, 4, 5, 6, 7, 8} //定义一个长度为8的int类型数组
fmt.Println(a2)
fmt.Println(a1) // go run [0 0 0]
fmt.Println(a_list) // go run [1 2 3 4 5 6 7 8]
//访问数组元素
code_list := [...]string{"go", "python", "java", "c++", "base", "shell"}
fmt.Println(code_list[0]) //访问数组索引第0个元素
fmt.Println(code_list[3])
code_list[0] = "Golang" //重置元素值
fmt.Println(code_list[0])
//遍历数组 通过for循环获得数组长度以此遍历
for i := 0; i < len(code_list); i++ {
fmt.Println(i, code_list[i])
}
//使用for range遍历数组
for i, v := range code_list {
fmt.Println(i, v)
}
}
func main() {
test1()
println("OK")
}
切片 类似python的列表,可以增删改和访问
package main
import "fmt"
//切片
func test2() {
//定义切片 var 数组名称 []数组类型
var q1 []int
var q2 = []string{"go", "python", "java", "c++", "base", "shell"} //数组初始化
//使用make函数生成切片,可以设置切片长度
var q3 = make([]int, 10)
//把q2 拷贝到q22
var q22 = make([]string, 10)
copy(q22, q2)
q4 := q2[1:3] //切片切割
var q5 = []int{10, 20, 30} //[10 20 30]
fmt.Println(q1) //[]
fmt.Println(q2) //[go python java c++ base shell]
fmt.Println(q3) //[0 0 0 0 0 0 0 0 0 0]
fmt.Println(q4) //[python java]
fmt.Println(q5)
fmt.Println("Q22", q22)
//切片遍历
//通过for循环获得长度以此遍历
for i := 0; i < len(q2); i++ {
fmt.Println(i, q2[i])
}
//使用for range遍历
for i, v := range q2 {
fmt.Println(i, v)
}
//切片添加和删除
//使用append函数添加元素
q1 = append(q1, 1, 2, 3, 4, 5)
fmt.Println(q1) //[1 2 3 4 5]
fmt.Println(q1)
}
func main() {
test2()
println("OK")
}
MAP 类似python的字典
package main
import "fmt"
//map 字典
func test3() {
//声明map和赋值
var info = map[string]string{ //使用等号map声明并使用{}赋值
"name": "Mek",
}
info2 := make(map[string]string) //使用make函数生成map
info2["name"] = "Mek" //使用["key"]赋值
info2["age"] = "20"
fmt.Println(info)
fmt.Println(info2)
fmt.Println(info2["name"]) //通过key获取值
//判断某个key是否有值
v,ok := info2["name"]
println(v,ok) //Mek true
v2,ok2 := info2["xxx"]
println(v2,ok2) // false
//遍历map
// 只拿到key
for k := range info2{
println(k) //name age
}
// 拿key和v
for k,v := range info2{
println(k,v) //name Mek age 20
}
//只拿v
for _,v := range info2{
println(v) //Mek 20
}
}
func main() {
test3()
println("OK")
}
func main() {
test3()
println("OK")
}
9.函数
函数的go语言中的一级公民,我们把所有的功能单元都定义在函数中,可以重复使用。函数包含函数的名称、
数列表和返回值类型,这些构成了函数的签名(signature)。
go语言中函数特性
1.Go语言中有3种函数:普通函数、屋名函数(没有名称的函数)、方法(定义在stu上的函数)。
2.Go语言中不允许函数重载(overload),也就是说不允许函数同名。
3.Go语言中的函数不能嵌套函数,但可以嵌套名函数。
4.函数是一个值,可以将函数赋值给变量,使得这个变量也成为函数。
5.函数可以作为参数传递给另一个函数。
6.函数的返回值可以是一个函数。
7.函数调用的时候,如果有参数传递给函数,则先拷贝参数的副本,再将副本传递给函数。
8.函数参数可以没有名称.
package main
import "fmt"
/*Go中经常会使用其中一个返回值作为函数是否执行成功、是否有错误信息的判断条件。例如return
value,exists、return valueok、return valueerr等。*/
/*当函数的返回值过多时,例如有4个以上的返回值,应该将这些返回值收集到容器中,然后以返回容器的方式
去返回。例如,同类型的返回值可以放进slice中,不同类型的返回值可以放进map中。
但函数有多个返回值时,如果其中某个或某几个返回值不想使用,可以通过下划线_来丢弃这些返回值。例
如下面的f1函数两个返回值,调用该函数时,丢弃了第二个返回值b,只保留了第一个返回值a赋值给了变
量a。*/
//定义函数 func 函数名(接收值,接收值)(返回值) {函数体}
//函数可以有0或多个参数,参数需要指定数据类型
func sum(a int,b int) (ret int) {
ret = a + b
return ret
}
//只有返回值的函数
func getNameAge() (name string,age int) {
name = "Mek"
age = 18
return name ,age
}
//没有写具体返回值的函数
func getNameAge2() (name string,age int) {
name = "Mek"
age = 18
return //等于return name ,age
}
//重新定义返回值名称
func getNameAge3() (name string,age int) {
n := "Mek"
a := 18
return n,a
}
//函数可以修改容器参数内的值
func f2(s []int) {
s[0]=999
}
//arge ...数据类型表示可以任意传参
func f3(args ...int) {
for _,v := range args{
fmt.Println(v)
}
}
func main() {
//调用函数并传参
ret := sum(3,4)
fmt.Println(ret)
name,age := getNameAge3()
fmt.Println(name,age)
s := []int{1,2,3}
f2(s)
fmt.Println(s) // [999 2 3]
f3(1,2,3,4,5) //调用可以任意传参的函数
}
高阶函数
Go语言的函数,可以作为函数的参数,传递给另外一个函数,作为另外一个函数的返回值返回.
package main
import "fmt"
//函数接收值是一个函数
//定义一个函数打印Hello
func sayHello(name string) {
fmt.Println("Hello",name)
}
//定义一个函数需要传一个sgring和一个func
func f1(name string,f func(string)) {
f(name)
}
//函数的返回值是一个函数
func add(a int,b int)int {
return a+b
}
func sub(a int,b int)int {
return a-b
}
func cel(oper string)func(int,int)int {
switch oper {
case "+":
return add
case "-":
return sub
default:
return nil
}
}
func main() {
//调用f1 并传入name和sayHello
f1("Mek",sayHello)
ff :=cel("-") //调用cle获得返回的函数
println(ff(3, 2)) // 运行ff 得到结果 1
}
匿名函数
Go语言函数不能嵌套,但是在函数内部可以定义匿名函数,实现一下简单功能调用。
所谓匿名函数就是,没有名称的函数。
package main
//匿名函数 没有函数名的函数,定义格式
// 变量名 := func(接收)(返回){函数体}
func main() {
max := func(a int,b int)(int) {
if a>b {
return a
}else {
return b
}
}
//调用匿名函数
println(max(8, 6)) //8
println(max(6,8)) //8
}
闭包
闭包可以理解成定义在一个函数内部的函数。在本质上,闭包是将函数内部和函数外部连接起来的桥架。或者说是函数和其引用环境的组合体。闭包指的是一个函数和与其相关的引用环境组合而成的实体。简单来说,闭包=函数+引用环境。
package main
//闭包
func add() func()int {
x :=10
return func() int {
x = x+1
return x
}
}
func main() {
f := add()
//在f的生命周期内x一直有效且每次被调用都会执行内部函数
println(f()) //11
println(f()) //12
println(f()) //13
println(f()) //14
println(f()) //15
}
递归
函数内部调用函数自身的函数称为递归函数。
使用递归函数最重要的三点:
1.递归就是自己调用自己。
2.必须先定义函数的退出条件,没有退出条件,递归将成为死循环。
3.go语言递归函数很可能会产生一大堆的goroutine,也很可能会出现栈空间内存溢出问题。
package main
var a int = 1
func f1() {
a += 1
println("...............", a)
f1() //f1 调用f1 就叫递归
}
func f2() {
a += 1
println(a)
if a>=10000000 { //设定一个退出条件
println("--------end--------")
}else {
f2()
}
}
func main() {
f2()
}
10.defer语句
80语言中的defer语句会将其后面跟随的语句进行“延退一处理。在defer归属的函数即将返回时,将延退处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行.
defer特性
1关键字defer用于注册延退调用。
2.这些调用直到return前才被执。因此,可以用来做资源清理。
3.多个defer语句,按先进后出的方式执行。
4.defer语句中的变量,在defer声明时就决定了。
defer用途
1.关闭文件句柄
2.锁资源释放
3.数据库连接释放
package main
func main() {
println("start")
defer println("Nets 1")
defer println("Nets 2")
defer println("Nets 3")
defer println("Nets 4")
println("end")
}
/* 输出结果
start
end
Nets 4
Nets 3
Nets 2
Nets 1
*/
11.init函数
golang有一个特殊的函数init函数,先于main函数执行,实现包级别的一些初始化操作。
-
init函数先于main函数自动执行,不能被其他函数调用;
-
init函数没有输入参数、返回值;
-
每个包可以有多个init函数;
-
包的每个源文件也可以有多个init函数,这点比较特殊;
-
同一个包的init执行顺序,golang没有明确定义,编程时要注意程序不要依赖这个执行顺序。
-
不同包的init函数按照包导入的依赖关系决定执行顺序。
运行顺序 变量初始化==>init()==>main()
*可以理解为python class 的 def init
package main
func init() {
println("Run init()")
}
func init() {
println("Run init2()")
}
func main() {
println("Run main()")
}
/* 输出结果
Run init()
Run init2()
Run main()
*/
12.指针
Go语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变
量。传递数据使用指针,而无须烤贝数据。
类型指针不能进行偏移和运算。
Go语言中的指针操作非常简单,只需要记住两个符号:& *
package main
func main() {
var ip *int //声明一个指针
println(ip) //0x0 未赋值前指针为空
i := 1
ip = &i
println(ip) // 0xc000045f60 直接打印取内存地址
println(*ip) // 1 *取值
i = 5
println(*ip) //5 修改指针对应的值后指针的值也会改变
}
结构体 *类似python的class
1.结构体
Go语言没有面向对象的概念了,但是可以使用结构体来实现,面向对象编程的一些特性,例如:继承、组合等特
性。
#定义一个结构体
type struct_variable_type struct {
name string
aeg int
sex bool
}
type:结构体定义关键字
struct_variable_type:结构体类型名称
struet:结构体定义关键字
member definition:成员定义
2.结构体操作
package main
import "fmt"
//定义一个结构体
type Person struct {
id int
name string
age int
email string
}
func main() {
//新建对象
var Mek Person
zhongX := Person{}
fmt.Println(Mek)
fmt.Println(zhongX)
//结构体对象赋值
Mek.id = 1 //对象属性赋值
Mek.age = 18
Mek.name = "Mek"
Mek.email = "[email protected]"
//创建时赋值
LiaoQ := Person{id: 3, name: "Q", age: 18, email: "[email protected]"} //键值对初始化赋值
liuL := Person{4, "LiuL", 18, "[email protected]"} //按顺序赋值
fmt.Println(Mek)
fmt.Println(LiaoQ)
fmt.Println(liuL)
//匿名结构体,在创建对象时直接设置对象属性
var zhaoRJ struct {
name string
age int
}
zhaoRJ.name = "zhaorenjie"
zhaoRJ.age = 18
fmt.Println(zhaoRJ)
}
3.结构体作为函数参数
Go结构体可以像普通变量一样,作为函数的参数,传递给函数,这里分为两种情况:
1.直接传递结构体,这是是一个副本(拷贝),在函数内部不会改变外面结构体内容.
2.传递结构体指针,这时在函数内部,能够数变外部结构体内容.
package main
import "fmt"
type Person struct {
id int
name string
}
func setPerson(person Person) { //定义一个函数接收对象
person.id = 99
person.name="root"
}
func setPersonp(person *Person) { //定义一个函数接收指针
person.id = 999
person.name = "root"
}
func main() {
Mek := Person{1,"Mek"}
fmt.Println("最开始",Mek)
setPerson(Mek) //传递给接收对象函数
fmt.Println("作为参数传递后",Mek)
var Mek_p = &Mek //创建指针
setPersonp(Mek_p) //传递给接收指针函数
fmt.Println("传递指针修改后",Mek)
}
4.结构体嵌套
Go语言没有面向对象输程思想,也没有继承关系,但是可以通过结构体嵌套来实现这种效果。
下面通过实例演示如何实现结构体嵌套,加入有一个人People结构体,这个人还有手机Phone结构体。
package main
import "fmt"
//结构体嵌套
type Phone struct { //创建一个手机结构体
logo string
model string
}
type People struct { //创建一个人结构体
phone Phone //人有手机
name string
age int
}
func main() {
iphone13 := Phone{"apple","13"} //创建一个手机对象
mek := People{
phone: iphone13, //人的手机对象绑定刚刚创建的手机
name: "Mek",
age: 18,
}
lcy := People{ //创建时一起赋值
phone: Phone{"REDMI","K50"},
name: "Li Chun Yan",
age: 35,
}
fmt.Println(lcy) //{{REDMI K50} Li Chun Yan 35}
fmt.Println(mek) //{{apple 13} Mek 18}
fmt.Println(mek.phone.model) //13
}
5.Go结构体的方法
Go语言没有面向对象的特性,也没有类对象的概念。但是,可以使用结构体来模拟这些特性,我们都知道面向对
象里面有类彦法等概念。我们也可以声明一些方法,属于某个结构体。
Go中的方法,是一种特殊的函数,定义于struct之上(与struct关联、绑定),被称为struc的接受者(receive)
通俗的讲,方法就是有接收者的函数。类似python的类方法,只是把类的类方法分开写了
*结构体实例,有值类型和指针类型,那么方法的接收者是结构体,那么也有值类型和指针类型。区别就是接收者是否复制结构体副本。值类型复制,指针类型不复制
package main
import "fmt"
type Syet struct {
id int
name string
}
//将该方法绑定到Syet,per在函数内指调用该方法的对象
func (per Syet) showid() {
fmt.Println(per.id)
}
func (per Syet) Chi() {
fmt.Println(per.name,"在吃饭.......")
}
func (per *Syet)setName() { //声明该函数接收Syet指针类型
newName := per.name + "_ADMIN"
per.name = newName
}
func main() {
lcy := Syet{
id: 1,
name: "LCY",
}
lcy.Chi() //调用该对象的方法 LCY 在吃饭.......
lcy.showid()
lcy_p := &lcy //创建对象指针
lcy_p.setName() //调用指针方法
lcy.Chi() //LCY_ADMIN 在吃饭....... 对象属性已被修改
}
接口
接口像是一个公司里面的领导,他会定义一些通用规范,只设计规范,而不实现规范。
Go语言的接口,是一种新的类型定义,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方
法就是实现了这个接口。
*接口定义实现了那些方法该模块的结构体就一定要实现那个方法
*一个类型可以实现多个接口
*多个类型可以实现同一个
一个类型实现多个接口,例如:有一个Player接口可以播放音乐,有一个Video接口可以播放视频,一个手机Mobile实现这两个接口,既可以播放音乐,又可以播放视频。
package main
import "fmt"
type Hard_Disker interface { //定义了一个硬盘接口类型 并且实现了 读取和写入两种
read()
write()
}
//定义一个机械硬盘对象
type HDD struct {
mode string
name string
}
//定义一个固态硬盘对象
type SSD struct {
mode string
name string
}
//机械硬盘实现读和写
func (hdd HDD)read() {
fmt.Println(hdd.name,"Reading........")
}
func (hdd HDD)write() {
fmt.Println(hdd.name,"Writeing........")
}
//固态硬盘实现读和写
func (ssd SSD)read() {
fmt.Println(ssd.name,"Reading........")
}
func (ssd SSD)write() {
fmt.Println(ssd.name,"Writeing........")
}
func main() {
st := HDD{
mode: "16T",
name: "备份盘",
}
samsung := SSD{
mode: "500G",
name: "系统盘",
}
//调用结构体函数
st.read()
st.write()
samsung.read()
samsung.write()
}
结构嵌套
假设我有读和写两个接口,我现在硬盘需要实现读和写,加密硬盘只需要实现读
package main
import "fmt"
type Reader interface { //读接口实现读
read()
}
type Writers interface { //写接口实现写
write()
}
type HardDisk interface { //硬盘需要实现读写
Reader
Writers
}
type encryptionHardDisk interface { //加密硬盘只需要实现读
Reader
}
//定义硬盘结构体
type SSD struct {
name string
}
type EncryptedHardDrive struct {
name string
}
//实现方法
func (ssd SSD)read()() {
fmt.Println(ssd.name,"Reading......")
}
func (ssd SSD)write()() {
fmt.Println(ssd.name,"Writeing......")
}
//EncryptedHardDrive只需要实现读取即可
func (ed EncryptedHardDrive)read()() {
fmt.Println(ed.name,"Reading......")
}
func main() {
//生成对象调用函数
sn350 := SSD{name: "SN350"}
sn350.read()
sn350.write()
is903 := EncryptedHardDrive{name: "IS903"}
is903.read()
}
构造函数
Go没有构造函数的概念,可以使用函数来模拟构造函数的的功能
package main
import "fmt"
type SSD struct {
name string
capacity string
}
//SSD的构造函数 类型python class 的 def __init__
func NewSSD(name string,capacity string)(*SSD,error) {
if name == "" {
return nil, fmt.Errorf("硬盘名称不存在!")
}else if capacity == "" {
return nil,fmt.Errorf("容量设置错误!")
}else {
return &SSD{name:name, capacity: capacity,},nil
}
}
func main() {
sn250 ,_ := NewSSD("sn250","500G") //通过NewSSD构造一个SSD对象
fmt.Println(sn250.name,sn250.capacity) //sn250 500G
}
实战演练
要求:
定义三个接口
–硬件 实现硬件自检功能
–硬盘 实现读和写功能并且需要实现硬件接口的全部功能
–计算机 实现开机 关机 显示 播放功能
定义计算机相关的硬件结构和计算机本结构,都需要实现硬件自检功能,硬盘需要实现读写功能,计算机本体需要实现计算机接口的全部功能和部分其他功能
package main
import "fmt"
//接口结构实战演练
//定义接口
type HWER interface { //定义硬件接口
self_test() //实现自检功能
}
type HardDiskER interface { //定义硬盘接口
HWER
read() //实现读和写
writer()
}
type Computerer interface { //定义计算机接口
off()
no()
show()
play()
}
//定义结构并实现接口功能
type CPU struct {
model string
}
func (cpu CPU)self_test() {
fmt.Println(cpu.model,".....OK!")
}
type GPU struct {
model string
}
func (gpu GPU)self_test() {
fmt.Println(gpu.model,".....OK!")
}
type Mainboard struct {
model string
}
func (mainboard Mainboard)self_test() {
fmt.Println(mainboard.model,".....OK!")
}
type RAM struct {
model string
size string
}
func (ram RAM)self_test() {
fmt.Println(ram.model,".....OK!")
}
type SSD struct {
model string
size string
}
func (ssd SSD)self_test() {
fmt.Println(ssd.model,".....OK!")
}
func (ssd SSD)read() {
fmt.Println(ssd.model,"Reading.....")
}
func (ssd SSD)writer() {
fmt.Println(ssd.model,"Writering.....")
}
//定义主要对象结构
type Computer struct {
model string
user string
CPU CPU
RAM RAM
GPU GPU
Mainboard Mainboard
SSD SSD
}
//实现接口方法和对象方法
func (computer Computer)no() {
fmt.Println(computer.model,"Power ON.....")
computer.CPU.self_test()
computer.RAM.self_test()
computer.GPU.self_test()
computer.Mainboard.self_test()
computer.SSD.self_test()
fmt.Println("load System.....")
computer.SSD.read()
fmt.Println(computer.user,"Login.....")
}
func (computer Computer)off() {
fmt.Println(computer.model,"Power OFF.....")
}
func (computer Computer)show() {
fmt.Println("Work 3D")
computer.SSD.read()
fmt.Println(computer.GPU.model,"Working.....")
}
func (computer Computer)play() {
computer.SSD.read()
fmt.Println("Music Playing.....")
}
func (Computer Computer)info() {
Computer.SSD.read()
fmt.Println("打印硬件信息:")
fmt.Println(Computer.model)
fmt.Println(Computer.user)
fmt.Println(Computer.CPU.model)
fmt.Println(Computer.Mainboard.model)
fmt.Println(Computer.RAM.model,Computer.RAM.size)
fmt.Println(Computer.GPU.model)
fmt.Println(Computer.SSD.model,Computer.SSD.size)
}
func (computer *Computer)setNewUser(newName string) {
fmt.Println("旧用户名:",computer.user)
computer.user = newName
fmt.Println("新用户名:",computer.user)
}
func main() {
Mybook := Computer{ //实例化对象
model: "Acer",
user: "Mek",
CPU: CPU{model: "i7 8086K"},
RAM: RAM{model: "SAMSUNG",size: "16G"},
GPU: GPU{model: "RTX2080Ti"},
Mainboard: Mainboard{model: "ASUS Z370_P"},
SSD: SSD{model: "SN750",size: "500G"},
}
//调用对象方法
Mybook.no()
Mybook.show()
Mybook.info()
Mybook_p := &Mybook //创建指针
Mybook_p.setNewUser("root")
fmt.Println(Mybook.user) //验证是否修改成功
Mybook.play()
Mybook.off()
}