当前位置: 代码迷 >> 综合 >> go学习———第二阶段
  详细解决方案

go学习———第二阶段

热度:33   发布时间:2023-12-06 08:53:08.0

go 第二阶段学习

  • 一、函数
    • 1、函数基本用法
      • 函数的参数与返回值
      • 不定参数的传递
    • 2、函数类型
      • 递归函数
      • 回调函数
      • 匿名函数
    • 3、defer的用法(先入后出)
    • 4、闭包与匿名函数
  • 二、指针变量
  • 三、数组与切片
    • 1、数组
    • 2、切片
      • 随机数
  • 四、map
  • 五、结构体
    • 1、结构体中指针的应用
    • 2、匿名字段

一、函数

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 = gmin = h} else {
    max = hmin = g}return
}

不定参数的传递

//不定参数传递
//参数的全部传递
func ddd(s ...string) {
    //将ddd全部参数传递给cccccc(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不定参数的前几位传递过去给ffffff(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 mainimport ("fmt"
)//实现1到100的求和
func C() {
    var sum intfor 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 intfmt.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 mainimport ("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 FuncTypes = Xg := s(1, 2)fmt.Printf("result=%d\n", g)s = Yg = s(1, 2)fmt.Printf("result=%d\n", g)s = Zg = 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) intfunc 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 := 7str := "小仙女"func (){
    a = 9str = "嘿嘿嘿"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()//声明一个函数类型的变量f2var f2 sss//将f1赋值给f2f2 = 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 = mmin = n}else{
    max = nmin = 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)stringvar f5 gggf5 = f4f5("阳光很暖","微风正好")
}

3、defer的用法(先入后出)

func main() {
    a := 10b := 20defer func(){
    fmt.Println(a,b) //a=7 b=9}()a = 7b = 9fmt.Println(a,b)x := 2y := 3defer func(x,y int){
    fmt.Println(x,y)  //x=2 y=3 参数先传过 然后等待执行}(x,y)x = 5y = 6fmt.Println(x,y)
}

4、闭包与匿名函数

package mainimport "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才分配空间 初始化为0var x int //没有初始化 值为0x++return x*x //函数调用完毕 x 自动释放
}
//返回值为一个匿名函数[fnuc() int] 返回一个函数类型
func bbb() func() int{
    var x inti:= func() int{
    x++return x*x}return i
}

二、指针变量

package mainimport "fmt"func main(){
    var a int = 123fmt.Printf("a = %d\n",a)//变量的内存fmt.Printf("&a = %v\n",&a)//变量的地址//保存某个变量的地址 需要指针类型 *int 保存 int 的地址, **int 保存 *int 的地址//定义一个变量p 类型为*intvar p *int// 指针变量指向谁 就把谁的地址赋给变量p = &afmt.Printf("p = %v,a &a = %v\n",p,&a)//*p操作的不是p的内存 是p指向的内存 即a*p = 111 //a=111fmt.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,xfmt.Printf("x = %d , y = %d\n",x,y)
}
func swap2(p1,p2 *int){
    *p1,*p2=*p2,*p1
}

三、数组与切片

1、数组

package mainimport "fmt"func main(){
    //声明一个数组var arr1 [3]int//方法一 给数组各元素赋值k:=0for 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])}//数组的部分初始化 没有初始化的默认为0arr3 := [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) //truefmt.Println("arr5==arr6",arr5==arr6) //false//二维数组//有多少个[]就用多少各循环var a [3][5]intq := 0for 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 mainimport("fmt"
)
//数组做函数参数 是值传递
//实参数组的每个元素给形参数组拷贝一份
//形参数组是实参数组的复制品
func sss(a [5]int){
    a[0] = 7fmt.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-lowfmt.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 容量为7fmt.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] =333fmt.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]=666fmt.Println("cc = ",cc) //[5,666,7]fmt.Println("aa = ",aa) //[1,2,333,4,5,666,7]//
}

随机数

package mainimport ("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 mainimport "fmt"func main() {
    //定义一个类型为 map[int]string 的变量var a map[int]string//a[1] = "ggg" 错误 没有初始化故不能赋值//对于map 只有len(len=0) 没有capfmt.Println("len(a) = ",len(a))fmt.Println("a = ",a)//用make创建一个mapb := 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 不存在即falsej,m := c[1]if m == true{
    fmt.Println("c[1] = ",j)}else{
    fmt.Println("key值不存在")}//删除某个值 deletes :=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 mainimport ("fmt"
)func main() {
    //顺序初始化 必须每个成员都初始化 否则报错var s1 Student = Student{
    "hhh",3,1,12345,"北京"}fmt.Println("s1 = ",s1)//指定成员初始化 未初始化的成员自动赋值为0s2 := 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 = 3s.sex = 1s.id = 12345s.addr = "北京"fmt.Println("s = ",s)//指针有合法指向后 才能操作成员var g Studentvar p3 *Studentp3 = &gp3.name = "hhh"(*p1).age = 3p3.sex = 1p3.id = 12345p3.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 Studenta4 = a3fmt.Println("a4 = ",a4)//函数作为参数的传递test01(a4) //值传递fmt.Println("a4 = ",a4)  // 拷贝一份儿过去 故原来的值不改变test02(&a4) //地址传递fmt.Println("a4 = ",a4)  //创建一个指针指向原来的地址 故值会改变
}//定义一个结构体类型 存放学生变量
type Student struct{
    name stringage intsex intid intaddr string
}
func test01(s Student){
    s.name = "ggg"fmt.Println("s = ",s)
}
func test02(p *Student){
    p.name = "kkk"
}

1、结构体中指针的应用

package mainimport("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 stringage intsex int
}
type Student struct{
    Personid intaddr string
}
//类型别名
type long int
//方法
func (a long)add(b long)long{
      //(a = 2 b = 3)return a+b
}

2、匿名字段

package mainimport "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更详细//指定成员初始化 没有初始化的自动赋值为0s3 :=  Student{
    Person:Person{
    name:"ggg"},addr:"上海"}fmt.Printf("s3 = %+v\n",s3)}
type Person struct{
    name stringage intsex int
}
type Student struct{
    Person //只有类型 没有名字 匿名字段 继承了Person的成员id intaddr string
}
  相关解决方案