go学习———第二阶段

15 篇文章 0 订阅

一、函数

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
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值