数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数
2021-02-14 01:20
标签:程序 包名 流程 增加 未使用 流程控制 www 处理 内容 现在我们来建立一个完整的程序 在相同目录下新建 进入文件所在目录,打开命令行终端,执行: 会显示一些打印结果: 我们看到 接下来我们会分析这个例子。 每一个大型的软件工程项目,都需要进行工程管理。工程管理的一个环节就是代码层次的管理。 包,也称为库,如代码的一个包,代码的一个库,英文: 在高级编程语言层次,也就是代码本身,各种语言发明了包( 我们的项目结构是: 每一个 作为执行入口的源码,则强制包名必须为 在入口文件 该命令会解析 接着, 可以看到导入了官方的包 在包 对于包中小写的函数或者结构体中小写的字段,不能导出,其他包不能使用它, 结构体和函数会在后面的章节介绍,现在只需知道只有大写字母开头的结构体或函数,才能在其他包被人引用。 最后, 有个必须注意的事情是函数 Golang语言可以先声明变量,再赋值,也可以直接创建一个带值的变量。如: 可以看到 同时,作为一门静态语言, 如果执行将会报错: 提示声明变量未使用,这是 变量定义后,如果没有赋值,那么存在默认值。我们也可以定义常量,只需加关键字 常量一旦定义就不能修改。 我们再来看看基本的数据类型有那些: 输出: 数据类型基本有整数,浮点数,字符串,布尔值,数组,切片(slice) 和 字典(map) 。 没声明具体变量类型的时候,会自动识别类型,把整数认为是 所以当你需要使用确切的 切片可以像数组一样按下标取值,放值,也可以追加值: 切片追加一个值 同时,因为日常开发中,我们经常将两个数据进行映射,类似于查字典一样,先查字母,再翻页。所以字典 字典存储了一对对的键值: 结构如 键值结构字典: 如果不对字典进行初始化,作为引用类型,它是一个 而切片结构 打印: 同时切片有以下特征: 内置语法 在切片后面加三个点 我们取切片的值,除了可以通过下标取一个值,也可以取范围: 如果下标起始等于下标 我们可以把经常使用的代码片段封装成一个函数,方便复用: 使用时: 输出: 将函数外的变量 就算函数里面改了局部变量的值,函数外的变量还是不变的,如: 输出: 变量是有作用域的,作用域主要被约束在各级大括号 我们还可以实现匿名的函数如: 打印出: 本来函数在外部是这样的: 现在省略了函数名,定义后直接使用: 我是陈星星,欢迎阅读我亲自写的 数据结构和算法(Golang实现),文章首发于 阅读更友好的GitBook。 数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数 标签:程序 包名 流程 增加 未使用 流程控制 www 处理 内容 原文地址:https://www.cnblogs.com/nima/p/12724766.html包、变量和函数
一、举个例子
main.go
:// Golang程序入口的包名必须为 main
package main // import "golang"
// 导入其他地方的包,包通过 go mod 机制寻找
import (
"fmt"
"golang/diy"
)
// init函数在main函数之前执行
func init() {
// 声明并初始化三个值
var i, j, k = 1, 2, 3
// 使用格式化包打印
fmt.Println("init hello world")
fmt.Println(i, j, k)
}
// 函数,两个数相加
func sum(a, b int64) int64 {
return a + b
}
// 程序入口必须为 main 函数
func main() {
// 未使用的变量,不允许声明
//cannot := 6
fmt.Println("hello world")
// 定义基本数据类型
p := true // bool
a := 3 // int
b := 6.0 // float64
c := "hi" // string
d := [3]string{"1", "2", "3"} // array,基本不用到
e := []int64{1, 2, 3} // slice
f := map[string]int64{"a": 3, "b": 4} // map
fmt.Printf("type:%T:%v\n", p, p)
fmt.Printf("type:%T:%v\n", a, a)
fmt.Printf("type:%T:%v\n", b, b)
fmt.Printf("type:%T:%v\n", c, c)
fmt.Printf("type:%T:%v\n", d, d)
fmt.Printf("type:%T:%v\n", e, e)
fmt.Printf("type:%T:%v\n", f, f)
// 切片放值
e[0] = 9
// 切片增加值
e = append(e, 3)
// 增加map键值
f["f"] = 5
// 查找map键值
v, ok := f["f"]
fmt.Println(v, ok)
v, ok = f["ff"]
fmt.Println(v, ok)
// 判断语句
if a > 0 {
fmt.Println("a>0")
} else {
fmt.Println("a= 10 {
fmt.Println("out")
// 退出循环
break
}
a = a + 1
if a > 5 {
continue
} else {
fmt.Println(a)
}
}
// 循环语句
for i := 9; i
diy
文件夹,文件下新建一个diy.go
文件(名字任取):// 包名
package diy
// 结构体
type Diy struct {
A int64 // 大写导出成员
b float64 // 小写不可以导出
}
// 引用结构体的方法,引用传递,会改变原有结构体的值
func (diy *Diy) Set(a int64, b float64) {
diy.A = a
diy.b = b
return
}
// 值结构体的方法,值传递,不会改变原有结构体的值
func (diy Diy) Set2(a int64, b float64) {
diy.A = a
diy.b = b
return
}
// 小写方法,不能导出
func (diy Diy) set(a int64, b float64) {
diy.A = a
diy.b = b
return
}
// 小写函数,不能导出,只能在同一包下使用
func sum(a, b int64) int64 {
return a + b
}
go mod init
go run main.go
init hello world
1 2 3
hello world
type:bool:true
type:int:3
type:float64:6
type:string:hi
type:[3]string:[1 2 3]
type:[]int64:[1 2 3]
type:map[string]int64:map[a:3 b:4]
5 true
0 false
a>0
1
2
3
4
5
out
i=9
i=10
0 9
1 2
2 3
3 3
a 3
b 4
f 5
sum(h+i),h=4,i=6,10
type:diy.Diy:{2 0}
type:diy.Diy:{1 1}
type:diy.Diy:{1 1}
type:*diy.Diy:&{2 0}
type:*diy.Diy:&{1 1}
type:*diy.Diy:&{1 1}
type:*diy.Diy:&{2 0}
[]int64{0, 0, 0, 0, 0},cap:5,len:5
[]int64{},cap:5,len:0
map[string]int64{},len:0
map[string]int64{},len:0
[]int64(nil)
[]int64{1}
[]int64{1, 2, 3, 4, 5, 6}
[]int64{1, 2, 3, 4, 5, 6, 7, 8, 9}
[1 2]
[1 2]
[1 2 3 4 5 6 7 8 9]
[1 2 3 4 5 6 7 8 9]
Golang
语言只有小括号和大括号,不需要使用逗号来分隔代码,只有一种循环for
。二、工程管理:包机制
Library
或者Package
。比如,我们常常听到某程序员说:嘿,X哥,我知道Github
上有一个更好用的数据加密库,几千颗星呢。package
)机制来更好的管理代码,将代码按功能分类归属于不同的包。Golang
语言目前的包管理新机制叫go mod
。├── diy
│ └── diy.go
└── main.go
*.go
源码文件,必须属于一个包,假设包名叫diy
,在代码最顶端必须有package diy
,在此之前不能有其他代码片段,如diy/diy.go
文件中:// 包名
package diy
// 结构体
type Diy struct {
A int64 // 大写导出成员
b float64 // 小写不可以导出
}
main
,入口函数为func main()
,如main.go
文件中:// Golang程序入口的包名必须为 main
package main // import "golang"
// 导入其他地方的包,包通过 go mod 机制寻找
import (
"fmt"
"golang/diy"
)
main.go
文件夹下执行以下命令:go mod int
main.go
文件的第一行package main // import "golang"
,注意注释//
后面的import "golang"
,会生成go.mod
文件:module golang
go 1.13
Golang
编译器会将这个项目认为是包golang
,这是整个项目最上层的包,而底下的文件夹diy
作为package diy
,包名全路径就是golang/diy
。main.go
为了导入包,使用import ()
:// 导入其他地方的包,包通过 go mod 机制寻找
import (
"fmt"
"golang/diy"
)
fmt
和我们自已定义的包golang/diy
,官方的包会自动寻找到,不需要任何额外处理,而自己的包会在当前项目往下找。golang/diy
中,我们定义了一个结构体和函数:// 结构体
type Diy struct {
A int64 // 大写导出成员
b float64 // 小写不可以导出
}
// 小写函数,不能导出,只能在同一包下使用
func sum(a, b int64) int64 {
return a + b
}
Golang
用它实现了私有或公有控制,毕竟有些包的内容我们不想在其他包中被使用,类似Java
的private
关键字。Golang
的程序入口统一在包main
中的main
函数,执行程序时是从这里开始的:package main
import "fmt"
// init函数在main函数之前执行
func init() {
// 声明并初始化三个值
var i, j, k = 1, 2, 3
// 使用格式化包打印
fmt.Println("init hello world")
fmt.Println(i, j, k)
}
// 程序入口必须为 main 函数
func main() {
}
init()
会在每个包被导入之前执行,如果导入了多个包,那么会根据包导入的顺序先后执行init()
,再回到执行函数main()
。三、变量
// 声明并初始化三个值
var i, j, k = 1, 2, 3
// 声明后再赋值
var i int64
i = 3
// 直接赋值,创建一个新的变量
j := 5
var i int64
,数据类型是在变量的后面而不是前面,这是Golang
语言与其他语言最大的区别之一。Golang
在编译前还会检查哪些变量和包未被引用,强制禁止游离的变量和包,从而避免某些人类低级错误。如:package main
func main(){
a := 2
}
go run main.go
./main.go:26:2: cannot declared and not used
Golang
语言与其他语言最大的区别之一。const
,如: const s = 2
四、基本数据类型
// 定义基本数据类型
p := true // bool
a := 3 // int
b := 6.0 // float64
c := "hi" // string
d := [3]string{"1", "2", "3"} // array,基本不用到
e := []int64{1, 2, 3} // slice
f := map[string]int64{"a": 3, "b": 4} // map
fmt.Printf("type:%T:%v\n", p, p)
fmt.Printf("type:%T:%v\n", a, a)
fmt.Printf("type:%T:%v\n", b, b)
fmt.Printf("type:%T:%v\n", c, c)
fmt.Printf("type:%T:%v\n", d, d)
fmt.Printf("type:%T:%v\n", e, e)
fmt.Printf("type:%T:%v\n", f, f)
type:bool:true
type:int:3
type:float64:6
type:string:hi
type:[3]string:[1 2 3]
type:[]int64:[1 2 3]
type:map[string]int64:map[a:3 b:4]
bool
。int
(默认类型,一般视操作系统位数=int32或int64),int32
,int64
。float32
,float64
(默认类型,更大的精度)string
。int
类型,把带小数点的认为是float64
类型,如: a := 3 // int
b := 6.0 // float64
int64
或float32
类型时,你需要这么做: var a int64 = 3
var b float32 = 6.0
Golang
有数组类型的提供,但是一般不使用,因为数组不可变长,当你把数组大小定义好了,就再也无法变更大小。所以Golang
语言造出了可变长数组:切片(slice
),将数组的容量大小去掉就变成了切片。切片,可以像切东西一样。自动调整大小,可以切一部分,或者把两部分拼起来。 d := [3]string{"1", "2", "3"} // array,基本不用到
e := []int64{1, 2, 3} // slice
// 切片放值
e[0] = 9
// 切片增加值
e = append(e, 3)
3
进去需要使用append
关键字,然后将结果再赋给自己本身,这是Golang
语言与其他语言最大的区别之一,实际切片底层有个固定大小的数组,当数组容量不够时会生成一个新的更大的数组。map
开发使用频率极高,所以Golang
自动提供了这一数据类型,这是Golang
语言与其他语言最大的区别之一。 // 增加map键值
f["f"] = 5
// 查找map键值
v, ok := f["f"]
fmt.Println(v, ok)
v, ok = f["ff"]
fmt.Println(v, ok)
map[string]int64
表示键为字符串string
,值为整数int64
,然后你可以将f = 5
这种关系进行绑定,需要时可以拿出键f
对应的值。五、slice 和 map 的特殊说明
map
使用前必须初始化,如: m := map[string]int64{}
m1 = make(map[string]int64)
nil
空引用,你使用空引用,往字典里添加键值对,将会报错。slice
不需要初始化,因为添加值时是使用append
操作,内部会自动初始化,如: var ll []int64
fmt.Printf("%#v\n", ll)
ll = append(ll, 1)
fmt.Printf("%#v\n", ll)
[]int64(nil)
[]int64{1}
ll = append(ll, 2, 3, 4, 5, 6)
fmt.Printf("%#v\n", ll)
ll = append(ll, []int64{7, 8, 9}...)
fmt.Printf("%#v\n", ll)
fmt.Println(ll[0:2])
fmt.Println(ll[:2])
fmt.Println(ll[0:])
fmt.Println(ll[:])
append
可以传入多个值,将多个值追加进切片。并且可以将另外一个切片,如[]int64{7, 8, 9}...
,用三个点表示遍历出里面的值,把一个切片中的值追加进另外一个切片。...
表示虚拟的创建若干变量,将切片里面的值赋予这些变量,再将变量传入函数。[下标起始:下标截止(不包括取该下标的值)]
,如[0:2]
,表示取出下标为0和1
的值,总共有两个值,再比如[0:4]
,表示取出下标为0,1,2,3
的值。如果下标取值,下标超出实际容量,将会报错。0
,那么可以省略,如[:2]
,如果下标截止省略,如[2:]
表示从下标2
开始,取后面所有的值。这个表示[:]
本身没有作用,它就表示切片本身。六、函数
// 函数,两个数相加
func sum(a, b int64) int64 {
return a + b
}
Golang
定义函数使用的关键字是func
,后面带着函数名sum(a, b int64) int64
,表示函数sum
传入两个int64
整数a
和b
,输出值也是一个int64
整数。 // 定义 int64 变量
var h, i int64 = 4, 6
// 使用函数
sum := sum(h, i)
fmt.Printf("sum(h+i),h=%v,i=%v,%v\n", h, i, sum)
sum(h+i),h=4,i=6,10
h
,i
传入函数sum
作为参数,是一个值拷贝的过程,会拷贝h
和i
的数据到参数a
和b
,这两个变量是函数sum
内的局部变量,两个变量相加后返回求和结果。package main
import "fmt"
func changeTwo(a, b int) {
a = 6
b = 8
}
func main() {
a, b := 1, 2
fmt.Println(a, b)
changeTwo(a, b)
fmt.Println(a, b)
}
1 2
1 2
{}
里面,所以函数里面的变量和函数体外的变量是没有关系的,互相独立。 input := 2
output := func(num int) int {
num = num * 2
return num
}(input)
fmt.Println(output)
4
func A(num int) int {
num = num * 2
return num
}
output := func(num int) int {
num = num * 2
return num
}(input)
input
是匿名函数的输入参数,匿名函数返回的值会赋予output
。系列文章入口
文章标题:数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数
文章链接:http://soscw.com/essay/55062.html