一、函数
1、函数基本用法
函数的参数与返回值
//定义一个无参无返回值的函数
func sss() {
fmt.Println("今天小仙女超级超级开心呀!")
}
//定义一个有参无返回值的函数
func aaa(a string, b, c int, d float64) {
fmt.Printf("姓名:%s\n年龄:%d\n开心指数;%d\n爆表指数:%f\n", a, b, c, d)
}
//定义一个不定参数的函数
func bbb(g ...int) {
//输出不定参数的长度
fmt.Println("len(g)=", len(g))
//输出不定参数
for i := 0; i <= len(g)-1; i++ {
fmt.Printf("g[%d]=%d\n", i, g[i])
}
//使用foreach语句遍历输出各元素
for i, j := range g {
fmt.Printf("g[%d]=%d\n", i, j)
}
}
//定义一个无参有返回值的函数
func ggg() (int, int, int) { //返回值无名字
return 1, 2, 3
}
func hhh() (d string, e string, f string) { //定义返回值的名字
d = "小仙女今天没有课哈哈!"
e = "小仙女今天中午吃饭啦!"
f = "小仙女今天中午睡午觉啦!"
return
}+
//定义一个有参有返回值的函数
//max min 是返回值名称,其顺序和返回值顺序一样
//g h 是形参
func iii(g, h int) (max, min int) {
if g > h {
max = g
min = h
} else {
max = h
min = g
}
return
}
不定参数的传递
//不定参数传递
//参数的全部传递
func ddd(s ...string) {
//将ddd全部参数传递给ccc
ccc(s...)
}
func ccc(s ...string) {
//输出参数长度
fmt.Println("len(s)=", len(s))
//输出不定参数
for i := 0; i <= len(s)-1; i++ {
fmt.Printf("s[%d]=%s\n", i, s[i])
}
//用foreach语句遍历输出各元素
for i, j := range s {
fmt.Printf("s[%d]=%s\n", i, j)
}
}
//参数的部分传递
func eee(h ...string) {
//将eee不定参数的前几位传递过去给fff
fff(h[:2]...) //传递h[0]~h[2](不包括h[2])
//将不定参数的后面几位传递过去
fff(h[2:]...) //传递h[2]之后的全部参数(包括h[2])
}
func fff(h ...string) {
//输出参数长度
fmt.Println("len(h)=", len(h))
//用foreach语句遍历输出各元素
for i, j := range h {
fmt.Printf("h[%d]=%s\n", i, j)
}
}
2、函数类型
递归函数
package main
import (
"fmt"
)
//实现1到100的求和
func C() {
var sum int
for i := 1; i <= 100; i++ {
sum += i
}
fmt.Printf("sum=%d\n", sum)
}
//递归函数求1到100的和
func A(i int) int {
if i == 100 {
return 100
}
return i + A(i+1)
}
func B(i int) int {
if i == 1 {
return 1
}
return i + B(i-1)
}
//Fibonacci数列
func D(i int) int {
if i == 1 || i == 2 {
return i - 1
}
return D(i-1) + D(i-2)
}
func main() {
sum := A(1)
fmt.Println(sum)
sum = B(100)
fmt.Printf("sum=%d\n", sum)
C()
fmt.Println("*****************************************")
var h int
fmt.Printf("请输入一个正整数:")
fmt.Scan(&h)
result := D(h)
fmt.Printf("result=%d\n", result)
}
回调函数
//函数也是一种数据类型,通过type给一个函数类型起名
//没有函数名字,没有{}
type FuncType func(int,int) int
//实现求和
func sum(a,b int) int {
return a+b
}
//回调函数 函数有一个参数是函数类型
func aaa(a,b int , c FuncType) int {
return c(a,b)
}
func main() {
e := aaa(7,9,sum)
fmt.Println("result=",e)
}
package main
import (
"fmt"
)
type FuncType func(int, int) int
//类型别名
// type long int
// type char byte
//返回值没有定义名称,return后直接写返回的表达式
func X(a int, b int) int {
return a + b
}
func Y(a, b int) int {
return a - b
}
func Z(a, b int) int {
return a * b
}
func main() {
var s FuncType
s = X
g := s(1, 2)
fmt.Printf("result=%d\n", g)
s = Y
g = s(1, 2)
fmt.Printf("result=%d\n", g)
s = Z
g = s(1, 2)
fmt.Printf("result=%d\n", g)
fmt.Println("------------------------------------")
g = qqq(2, 3, 4, a)
fmt.Printf("result=%d\n", g)
g = qqq(2, 3, 4, b)
fmt.Printf("result=%d\n", g)
g = qqq(2, 3, 4, c)
fmt.Printf("result=%d\n", g)
}
//回调函数
type hhh func(int, int, int) int
func qqq(x int, y int, z int, m hhh) int {
fmt.Println("@@@@")
return m(x, y, z)
}
func a(x int, y int, z int) int {
return x * y * z
}
func b(x int, y int, z int) int {
return x + y + z
}
func c(x int, y int, z int) int {
return x*y + z
}
匿名函数
package main
import (
"fmt"
)
func main() {
a := 7
str := "小仙女"
func (){
a = 9
str = "嘿嘿嘿"
fmt.Println(a,str)
}()
fmt.Println(a,str)
//匿名函数,没有函数名字
//用变量f1接收函数
f1 := func (){
fmt.Printf("a=%d\nstr=%s\n",a,str)
}
f1()//函数的调用
//给函数起一个别名(sss)然后调用
type sss func()
//声明一个函数类型的变量f2
var f2 sss
//将f1赋值给f2
f2 = f1
//调用函数
f2()
//定义匿名函数,同时调用
func (){
fmt.Printf("a=%d\nstr=%s\n",a,str)
}() //()代表调用此匿名函数
//函数必须调用 否则报错 或者可以找变量接收 如f1
//带参数的匿名函数
f3 := func (i, j int){
fmt.Printf("result = %d\n",i+j)
}
f3(10,20)
func (i,j int){
fmt.Printf("result = %d\n",i*j)
}(10,20)
//带参数有返回值的匿名函数
c,d:=func (m,n int) (max,min int){
if m>n{
max = m
min = n
}else{
max = n
min = m
}
return
}(10,20)
fmt.Println(c,d)
f4:= func (x,y string) string {
fmt.Println(x,y)
return x+y
}
f4("可可爱爱","开开心心")
//给函数起一个别名并调用
type ggg func(string,string)string
var f5 ggg
f5 = f4
f5("阳光很暖","微风正好")
}
3、defer的用法(先入后出)
func main() {
a := 10
b := 20
defer func(){
fmt.Println(a,b) //a=7 b=9
}()
a = 7
b = 9
fmt.Println(a,b)
x := 2
y := 3
defer func(x,y int){
fmt.Println(x,y) //x=2 y=3 参数先传过 然后等待执行
}(x,y)
x = 5
y = 6
fmt.Println(x,y)
}
4、闭包与匿名函数
package main
import "fmt"
func main() {
fmt.Println(aaa()) //1
fmt.Println(aaa()) //1
fmt.Println(aaa()) //1
// 将调用bbb()返回的函数赋给变量f
f := bbb()
//调用返回的函数
fmt.Println(f()) //1
fmt.Println(f()) //4
fmt.Println(f()) //9
//直接一次性调用bbb()和返回的函数
fmt.Println((bbb())()) //1
fmt.Println((bbb())()) //1
fmt.Println((bbb())()) //1
}
func aaa() int{
//函数被调用时 x才分配空间 初始化为0
var x int //没有初始化 值为0
x++
return x*x //函数调用完毕 x 自动释放
}
//返回值为一个匿名函数[fnuc() int] 返回一个函数类型
func bbb() func() int{
var x int
i:= func() int{
x++
return x*x
}
return i
}
二、指针变量
package main
import "fmt"
func main(){
var a int = 123
fmt.Printf("a = %d\n",a)//变量的内存
fmt.Printf("&a = %v\n",&a)//变量的地址
//保存某个变量的地址 需要指针类型 *int 保存 int 的地址, **int 保存 *int 的地址
//定义一个变量p 类型为*int
var p *int
// 指针变量指向谁 就把谁的地址赋给变量
p = &a
fmt.Printf("p = %v,a &a = %v\n",p,&a)
//*p操作的不是p的内存 是p指向的内存 即a
*p = 111 //a=111
fmt.Printf("*p = %v,a = %v\n",*p,a)
fmt.Println("****************************************8")
x,y:=10,20
//变量本身传递,即值传递
swap1(x,y)
fmt.Printf("x = %d , y = %d\n",x,y)
//变量地址传递,即址传递
swap2(&x,&y)
fmt.Printf("x = %d , y = %d\n",x,y)
}
func swap1(x,y int){
x,y = y,x
fmt.Printf("x = %d , y = %d\n",x,y)
}
func swap2(p1,p2 *int){
*p1,*p2=*p2,*p1
}
三、数组与切片
1、数组
package main
import "fmt"
func main(){
//声明一个数组
var arr1 [3]int
//方法一 给数组各元素赋值
k:=0
for i:=0;i<3;i++ {
k++
arr1[i] = k
}
fmt.Println("arr1 = ",arr1)
//方法二 给数组各元素赋值
for i := 0;i<len(arr1);i++{
arr1[i]=i+3
}
fmt.Println("arr1 = ",arr1)
//用forrange语句遍历输出各元素
for m,n := range arr1{
fmt.Printf("arr[%d]=%d\n",m,n)
}//[3,4,5] 就近原则
//声明一个数组并完成初始化
arr2 := [3]int{1,2,3}
for i:=0;i<3;i++{
fmt.Printf("arr2[%d]=%d\n",i,arr2[i])
}
//数组的部分初始化 没有初始化的默认为0
arr3 := [3]int{0:7,2:9}
for i:=0;i<3;i++{
fmt.Printf("arr3[%d]=%d\n",i,arr3[i])
}
//数组的比较 只比较各元素是否相等
arr4 := [5]int{1,2,3,4,5}
arr5 := [5]int{1,2,3,4,5}
arr6 := [5]int{2,3,4,5,7}
fmt.Println("arr4==arr5",arr4==arr5) //true
fmt.Println("arr5==arr6",arr5==arr6) //false
//二维数组
//有多少个[]就用多少各循环
var a [3][5]int
q := 0
for i:=0;i<3;i++{
for j := 0;j<5;j++{
q++
a[i][j] = q
//输出第一行的元素
fmt.Printf("a[%d][%d] = %d ",i,j,a[i][j])
}
//换行
fmt.Printf("\n")
}
fmt.Println("a = ",a)
//多维数组的初始化
s := [3][4]int {{1,2,3,4},{5,6,7,8},{9,10,11,12}}
fmt.Println("s=",s)
2、切片
package main
import(
"fmt"
)
//数组做函数参数 是值传递
//实参数组的每个元素给形参数组拷贝一份
//形参数组是实参数组的复制品
func sss(a [5]int){
a[0] = 7
fmt.Println("a1 = ",a)
}
func main() {
a := [5]int{1,2,3,4,5}
sss(a)
fmt.Println("a2 = ",a) //[7,2,3,4,5]
array := [...]int{1,2,3,4,5,6,7,8,9}
slice := array[0:3:5]
//此切片是从数组array的第0个元素开始取(3-0)个元素 长度为(3-0=3) 容量为(5-0=5)
//[low : high : max]
//low 下标的起点
//high 下标的终点(不包括此下标) [a[low],a[high]]左闭右开
//长度:len = high-low 容量: cap = max-low
fmt.Println("array = ",array)
fmt.Println("len(array) = ",len(array))
fmt.Println("cap(array) = ",cap(array))
fmt.Println("slice = ",slice)
fmt.Println("len(slice) = ",len(slice))
fmt.Println("cap(slice) = ",cap(slice))
b := array[2:7:9]//从第3个元素[下标为2]开始取5个元素 长度为5 容量为7
fmt.Println("b = ",b)
fmt.Println("len(b) = ",len(b))
fmt.Println("cap(b) = ",cap(b))
e := b[:]//[0:len(b):len(b)] 不指定容量和长度一样
fmt.Println("e = ",e)
fmt.Printf("len(e) = %d,cap(e) = %d\n",len(e),cap(e))
//append函数 给slice末尾添加数据 返回新的slice对象
//添加一个元素
b = append(b,999)
fmt.Println("b = ",b)
//添加两个元素
b = append(b,666,777)
fmt.Println("b = ",b)
//copy函数
x :=[]int{3,4}
y :=[]int{6,7,8,9,0}
copy(y,x)//后面的代替前面的
fmt.Println("y = ",y) //[3,4,8,9,0]
//自动推导类型 同时初始化
c := []int {6,7,8,9}
fmt.Println("c = ",c)
//make函数 格式 make(切片类型,长度,容量)
d := make([]int,4,4)
fmt.Println("d = ",d)
fmt.Printf("len(d) = %d,cap(d) = %d\n",len(d),cap(d))
//操作某个元素
f := c[1]
fmt.Println("f = ",f)
g := c[1:4:4]
fmt.Println("g = ",g)
fmt.Printf("len(g) = %d,cap(g) = %d\n",len(g),cap(g))
//从0开始取2个元素
h :=c[:2] //[6,7]
fmt.Println("h = ",h)
fmt.Printf("len(h) = %d,cap(h) = %d\n",len(h),cap(h))
//从下标为2(即第三个元素)开始取到末尾
i :=c[2:]
fmt.Println("i = ",i)
fmt.Printf("len(i) = %d,cap(i) = %d\n",len(i),cap(i))
aa :=[]int{1,2,3,4,5,6,7}
//新切片
bb :=aa[1:4] //从aa[1]开始取3个元素 即[2,3,4,]
bb[1] =333
fmt.Println("bb = ",bb) //[2,333,4]
fmt.Println("aa = ",aa) //[1,2,333,4,5,6,7]
//另外新切片
cc :=aa[4:7]//从aa[4]开始取3个元素 即[5,6,7]
cc[1]=666
fmt.Println("cc = ",cc) //[5,666,7]
fmt.Println("aa = ",aa) //[1,2,333,4,5,666,7]
//
}
随机数
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
//设置种子,只需一次
//如果种子参数一样,每次运行程序产生的随机数都一样
//rand.Seed(777)
rand.Seed(time.Now().UnixNano())//以当前系统时间作为种子参数
for i :=0;i<5;i++ {
//产生随机数
//fmt.Println("rand = ", rand.Int())//产生的随机数很大
fmt.Println("rand = ",rand.Intn(100))//限制在100以内
}
}
四、map
package main
import "fmt"
func main() {
//定义一个类型为 map[int]string 的变量
var a map[int]string
//a[1] = "ggg" 错误 没有初始化故不能赋值
//对于map 只有len(len=0) 没有cap
fmt.Println("len(a) = ",len(a))
fmt.Println("a = ",a)
//用make创建一个map
b := make(map[int]string)
//可以赋值
b[1] = "aaa"
b[2] = "bbb"
b[3] = "ccc"
fmt.Println("len(b) = ",len(b))
fmt.Println("b = ",b)
//声明一个map并进行初始化
c :=map[int]string{1:"ggg",2:"sss",3:"hhh"}
fmt.Println("c1 = ",c)
c[1] = "iii" //修改原来的值
fmt.Println("c2 = ",c)
c[4] = "yyy" //增加一个值 自动扩容
fmt.Println("c3 = ",c)
//遍历输出 (map 的输出是无序的 所以每次输出的结果不一定相同)
for i,j := range c{
fmt.Printf("%d ==========> %s\n",i,j)
}
//判断一个key值是否存在
//第一个返回值为key所对应的value 第二个返回值是bool类型的 值存在即true 不存在即false
j,m := c[1]
if m == true{
fmt.Println("c[1] = ",j)
}else{
fmt.Println("key值不存在")
}
//删除某个值 delete
s :=map[int]string{1:"ggg",2:"sss",3:"hhh",4:"kkk"}
fmt.Println("s = ",s)
delete(s,2)
fmt.Println("s = ",s)
//map做函数参数传递
test(s) //函数内部删除某个值
fmt.Println("s = ",s) //在外部同样删除了
}
func test(s map[int]string){
delete(s,1)
}
五、结构体
package main
import (
"fmt"
)
func main() {
//顺序初始化 必须每个成员都初始化 否则报错
var s1 Student = Student{"hhh",3,1,12345,"北京"}
fmt.Println("s1 = ",s1)
//指定成员初始化 未初始化的成员自动赋值为0
s2 := Student{name:"hhh",addr:"北京"}
fmt.Println("s2 = ",s2)
//指针
var p1 *Student = &Student{"hhh",3,1,12345,"北京"}
fmt.Println("*p1 = ",*p1)
p2 := &Student{name:"hhh",addr:"北京"}
fmt.Println("*p2 = ",*p2)
//单独操作构体变量
var s Student
//s := new (Student) 用new为s分配一片空间
s.name = "hhh"
s.age = 3
s.sex = 1
s.id = 12345
s.addr = "北京"
fmt.Println("s = ",s)
//指针有合法指向后 才能操作成员
var g Student
var p3 *Student
p3 = &g
p3.name = "hhh"
(*p1).age = 3
p3.sex = 1
p3.id = 12345
p3.addr = "北京"
fmt.Println("*p3 = ",*p3)
//结构体比较
a1 := Student{"hhh",3,1,12345,"北京"}
a2 := Student{"hhh",3,1,12345,"北京"}
a3 := Student{"hhh",7,1,12345,"北京"}
fmt.Println("a1==a2",a1==a2)
fmt.Println("a1==a3",a1==a3)
//同类型的结构体可以相互赋值
var a4 Student
a4 = a3
fmt.Println("a4 = ",a4)
//函数作为参数的传递
test01(a4) //值传递
fmt.Println("a4 = ",a4) // 拷贝一份儿过去 故原来的值不改变
test02(&a4) //地址传递
fmt.Println("a4 = ",a4) //创建一个指针指向原来的地址 故值会改变
}
//定义一个结构体类型 存放学生变量
type Student struct{
name string
age int
sex int
id int
addr string
}
func test01(s Student){
s.name = "ggg"
fmt.Println("s = ",s)
}
func test02(p *Student){
p.name = "kkk"
}
1、结构体中指针的应用
package main
import(
"fmt"
)
func main() {
//g := Student{Person{"hhh",3,1},12345,"beijing"}}
//fmt.Println("g = ",g)
//定义一个变量
var x long = 2 // long为int的别名
//变量名.方法名(参数)
result := x.add(3)
fmt.Println("result = ",result)
}
type Person struct{
name string
age int
sex int
}
type Student struct{
Person
id int
addr string
}
//类型别名
type long int
//方法
func (a long)add(b long)long{ //(a = 2 b = 3)
return a+b
}
2、匿名字段
package main
import "fmt"
func main() {
//顺序初始化
var s1 Student = Student{Person{"hhh",3,1,},12345,"北京"}
fmt.Println("s1 = ",s1)
//自动推导类型
s2 := Student{Person{"hhh",3,1,},12345,"北京"}
fmt.Printf("s2 = %+v\n",s2) //%+v 使输出的s2更详细
//指定成员初始化 没有初始化的自动赋值为0
s3 := Student{Person:Person{name:"ggg"},addr:"上海"}
fmt.Printf("s3 = %+v\n",s3)
}
type Person struct{
name string
age int
sex int
}
type Student struct{
Person //只有类型 没有名字 匿名字段 继承了Person的成员
id int
addr string
}