go基础2
go语法基本使用
包的管理
# 就是模块的意思
1.自定义包
go语言的代码必须放在gopath的src的路径下
包的导入是从gopath的src路径下开始检索的
除了main包以外,建议包的名字就叫文件夹的名字
同一个包下,变量和函数只能定义一次
同一个包下的变量和函数可以直接使用
包内的函数或变量,想让外部函数使用,必须首字母大写
以后下的第三方包就放在fopath的src下
-day1
-day2
-s1.go
package day2
import "fmt"
func init(){
fmt.Println("我是day2中的初始函数")
}
func Test(){
fmt.Println("我是day2下面的test函数")
fmt.Println(Name)
}
-s2.go
package day2
import "fmt"
var Name = "zc"
func Test1() {
fmt.Println("我是day2下面的test1函数")
fmt.Println(Name)
}
-s1.go
package main
import (
"day01/day2"
"fmt"
)
func main() {
day2.Test()
fmt.Println(day2.Name)
}
func init(){
fmt.Println("我是day2中的初始函数")
}
在包里面的go文件中定义这个初始函数,在一开始导报的时候就开始执行,并且可以定义多个.
初始化一些操作
包导入的几种方式
-import "day02/mypackage"
-给包重命名
-import 名字 "day02/mypackage"
名字.变量/函数
-包只导入,不使用
import _ "day02/mypackage"
go mod的使用
go语言没有一个统一包管理地址,大家都放在到github上面
go mod模式的使用
两种创建的方式
-set GO111MODULE=on
-命令行下输入:go mod init 项目名 在当前路径下创建出go.mod(该项目依赖go的版本,第三方包版本)
-在goland IDE设置里面settings->go Modules里配置 GOPROXY=https://goproxy.cn 这样就可以下载快点
- go get -u github.com/astaxie/beego 下载beego框架
go.mod中加入依赖
-以后把项目copy给别人,go install
-自己写的包,就放在自己项目路径下
-加代理的方式:手动写,goland中配置
-在goland中创建项目时,直接指定modules,可以配置环境变量(加代理)
条件语句
package main
import "fmt"
func main() {
a:= Test()
// if else
//if a >10 {
// fmt.Println("a是大于10")
//} else {
// fmt.Println("a小于10")
//}
// if - else if - else
if a>10 {
fmt.Println("a大于10")
} else if a==10{
fmt.Println("a等于10")
} else {
fmt.Println("a小于10")
}
}
func Test() int {
return 100
}
循环
没有while,do while 循环,只有一个for循环
package main
import "fmt"
//for 变量初始化;条件 变量自增/自减{}
func main() {
for i:=0;i<10;i++{
fmt.Println(i)
}
}
swicth
可以代替多条件if语句
package main
import "fmt"
func main() {
num:=2
switch num {
case 1,2,3:
fmt.Println("1")
fallthrough
case 4,5:
fmt.Println('2')
default:
fmt.Println("错误提示")
}
}
fallthrough:只要看到这个,无条件执行下一个case或者default
数组
是同一类元素的集合,是值类型
package main
import "fmt"
//数组就是同一类元素的集合,可以多个值,但是
func main() {
//定义大小为三的string类型数据,
//var name [3]string
//var ages [3]int8
//ages[0] = 99
//ages[1] = 88
//ages[2] = 77
//fmt.Println(ages)
//定义初始化
//var ages [3]int=[3]int{1,2,3}
//var ages=[3]int{1,2,3}
//ages:=[3]int{1,2,3} // 不能多放
//fmt.Println(ages)
//数组的其他用法
var ages = [...]int{1, 2, 3, 4, 5, 6, 7} // 数据里面的元素是多少个,他的大小就是多少
fmt.Println(ages)
test(ages) // 因为数组是值类型, 所有函数传参,都是copy传递
fmt.Println(ages)
}
func test(ages [7]int){
ages[0]=99
fmt.Println(ages)
}
//[1 2 3 4 5 6 7]
//[99 2 3 4 5 6 7]
//[1 2 3 4 5 6 7]
数组的循环
var ages = [...]int{1, 2, 3, 4, 5, 6, 7} // 数据里面的元素是多少个,他的大小就是多少
//数组的长度,在定义阶段已经固定
//fmt.Println(len(ages))
//方式一
for i := 0; i < len(ages); i++ {
fmt.Println(ages[i])
}
//方式二
for i:=range ages{
fmt.Println(i)//打印出来的是索引
}
for _,value:=range ages{
fmt.Println(value)
}//打印出来值
多维数组
a := [3][3]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}}
for _, value := range a {
for _, li := range value {
fmt.Println(li)
}
}
数组的定义并初始化
a := [...]int{10:99}
fmt.Println(a)//指定位置初始化
切片
数组看上去比较灵活,但是他有固定的长度限制,不能增加他的长度,所以要用切片
切片是由数组建立的一种方便,灵活且强大的包装,切片本身不能拥有任何数据,他们只是对现有数组的引用,就是指针指向了某个数组
package main
import "fmt"
func main() {
//1.切片的第一种方式
//定义数组
a := [...]int{1, 2, 3, 4, 5, 6, 7}
//基于数组,做一个切片
var b []int
b = a[:] //[]int不带任何东西就是切片
fmt.Println(b)
fmt.Printf("%T", b)
fmt.Printf("%T", a)
//2.使用切片
fmt.Println(b[0])
//3.修改切片
b[0]=999
fmt.Println(b)
//打印数组,数组会被修改,修改数组也会影响切片
fmt.Println(a)
//5.切片只切数组的一部分
var c []int = a[3:5]
fmt.Println(c)
//7.切片的长度和容量
fmt.Println(len(c))
//容量,最多能存多少
fmt.Println(cap(c))
//8.切片追加值
c = append(c, 6)
c = append(c, 88)
//到了临界点在追加
c = append(c, 77)
fmt.Println(c)
fmt.Println(a) //到了临界点后追加的元素数组不会增加.
fmt.Println(len(c))
//容量,最多能存多少
fmt.Println(cap(c)) //到了临界点之后会在原来的基础上翻倍,把原来的值copy到新的数组里面,就会脱离关系, 再去修改的话就不会改变
}
}
//切片可以继续切片
map
map 就是key-value数据结构,类似于集合
var map 变量名 map[keytype]valuetype
key:可以是bool,num,string, 指针,channel,我们常用的是int和string
声明:是不会分配内存的,初始化要make,分配内存后才能赋值和使用
package main
import "fmt"
func main() {
//map的声明和注意事项
//在使用map前,需要先make,make的作用是给map分配数据空间
//赋值方式一
a := make(map[string]string,10) //给他分配10个这样的内存空间
a["No.1"] = "松江"
a["No.2"] = "五十"
//赋值方式二
a := map[string]string{"No.1":"松江","No.2":"五十"}
fmt.Println(a)
}
map[No.1:松江 No.2:五十]
练习
package main
import "fmt"
func main() {
//存放三个学生信息,每个学生有name,sex
studentMap :=make(map[string]map[string]string)
studentMap["stuNo.1"] = make(map[string]string,2)
studentMap["stuNo.1"]["name"] = "tom"
studentMap["stuNo.1"]["sex"] = "男"
fmt.Println(studentMap)
}
map[stuNo.1:map[name:tom sex:男]]
map的crud
//增加和更新
map["key"]=value key有就更新,没有就增加
//删除
delete(map,"key") delete是一个内置函数,如果key存在就删除,不存在运行也不会出错
delete(a,"No.2")
//查找
val, ok := a["No.1"]
if ok {
fmt.Printf("有No.1,val为%v",val)
}else {fmt.Println("没有")}
//必须是ok
注意: 如果我们要删除map所有的key,没有一个专门的方法一次删除,可以遍历一下key,逐个删除,或者map = make(...),make一个新的,让原来的成为垃圾,被gc回收
a := make(map[string]string) //给他分配10个这样的内存空间
a["No.1"] = "松江"
a["No.2"] = "五十"
a = make(map[string]string)
fmt.Println(a)
map的遍历
map的遍历我们使用for-range来遍历
for i, v := range a {
fmt.Println(i, v)
}
案例
package main
import "fmt"
func main() {
studentMap :=make(map[string]map[string]string)
studentMap["stuNo.1"] = make(map[string]string,2)
studentMap["stuNo.1"]["name"] = "tom"
studentMap["stuNo.1"]["sex"] = "男"
studentMap["stuNo.2"] = make(map[string]string,2)
studentMap["stuNo.2"]["name"] = "jack"
studentMap["stuNo.2"]["sex"] = "女"
studentMap["stuNo.3"] = make(map[string]string,2)
studentMap["stuNo.3"]["name"] = "roll"
studentMap["stuNo.3"]["sex"] = "男"
for k1,v1 :=range studentMap{
fmt.Println("k1=",k1)
for k2, v2 := range v1{
fmt.Println("\t",k2,v2)
}
}
}
map切片
使用一个map来记录monster的信息name和age,一个monster对应一个map,并且妖怪的个数可以动态的增加
package main
import "fmt"
func main() {
//声明一个map切片
//对切片进行make
monsters := make([]map[string]string, 2)
//if monsters[0] == nil {
// monsters[0] = make(map[string]string, 2)
// monsters[0]["name"] = "牛魔王"
// monsters[0]["age"] = "500"
//}
//if monsters[1] == nil {
// monsters[1] = make(map[string]string, 2)
// monsters[1]["name"] = "铁扇"
// monsters[1]["age"] = "500"
//} //这样就是写死了,不能动态增加
//我们需要使用到切片的append函数,可以动态的增加monsters
newMonsters := map[string]string{
"name": "新的妖怪",
"age": "500",
}
monsters = append(monsters,newMonsters)
fmt.Println(monsters)
}
map的排序
package main
import (
"fmt"
"sort"
)
func main() {
//map的排序
map1 := map[int]int{10: 100, 4: 90, 9: 12}
fmt.Println(map1)
//如果按照map 的key顺序进行排序输出
//1. 先将map 的key放入切片中
//2. 对切片排序
//3. 遍历切片,按照key来输出map 的值
// 定义一个切片
var keys []int
for k, _ := range map1 {
keys = append(keys, k)
}
//排序
sort.Ints(keys)
fmt.Println(keys)
for _,k:=range keys{
fmt.Printf("map1[%v]=%v \n",k,map1[k])
}
}
map使用细节
-
map是引用类型,遵守引用类型传递的机制,在一个函数接收map,修改后,会直接修改原来的map
package main import "fmt" func modify(map1 map[int]int) { map1[10] = 900 } func main() { map1 := map[int]int{1: 90, 2: 288, 10: 88} modify(map1) fmt.Println(map1) } # map[1:90 2:288 10:900]
-
map 的容量达到后,在想map增加元素,会自动扩容,不会发生panic,map能自动增长键值对
package main import "fmt" func modify(map1 map[int]int) { map1[10] = 900 } func main() { map1 := make(map[int]int,2) map1[1]=1 map1[2]=1 map1[3]=1 map1[10]=1 modify(map1) fmt.Println(map1) }
-
map的value也经常使用struct类型,更适合管理复杂的数据,如value为students 的结构体
package main import "fmt" type Stu struct { Name string Age int address string } func main() { students := make(map[string]Stu,10) stu1 := Stu{"tom",10,"北京"} stu2 := Stu{"jack",101,"上海"} students["No.1"] = stu1 students["No.2"] = stu2 fmt.Println(students) for k,v := range students{ fmt.Printf("学生的编号%v \n",k) fmt.Printf("学生的姓名%v \n",v.Name) fmt.Printf("学生的编号%v \n",v.Age) fmt.Printf("学生的编号%v \n",v.address) fmt.Println("-----------") } } ~!
综合使用案例
-
使用map[string]map[string]string的类型
-
key表示用户名,是唯一的,不能重复
-
如果某个用户名存在,就将密码修改成88888,不存在就增加这个用户的信息
-
编写一个函数 modifyUser(users map[string]map[string]string,name string)完成上面的功能
package main import "fmt" func modifyUser(users map[string]map[string]string, name string) { //吸纳判断是否有name //v,ok:=users[name] if users[name] != nil { users[name]["pwd"] = "888888" } else { //没有这个用户 users[name] = make(map[string]string, 2) users[name]["pwd"] = "888888" users[name]["nickname"] = "昵称" + name } } func main() { users := make(map[string]map[string]string, 10) users["smith"] = map[string]string{"pwd":"9999","nickname":"xxxx"} modifyUser(users, "tom") modifyUser(users, "marry") fmt.Println(users) }