zoukankan      html  css  js  c++  java
  • go入门二

    一.流程控制

     1.选择结构

      if-else:

    package main
    
    import (
        "io/ioutil"
        "fmt"
    )
    
    func main(){
        const filename="abc.txt"
        //读文件
        content,err :=ioutil.ReadFile(filename)
        if err !=nil{
            fmt.Println(err)
        }else{
            fmt.Printf("%s
    ",content)
        }
    
        //if也支持如下语法
        if content,err :=ioutil.ReadFile(filename);err !=nil{
            fmt.Println(err)
        }else{
            fmt.Printf("%s
    ",content)
        }
    }

      switch:

    package main
    
    import "fmt"
    
    //传入成绩,返回评分等级
    func grade(score int) string {
        //定义字符串
        g := ""
        //go为switch每一句都加了break
        switch {
        case score < 0 || score > 100:
            g = "输入错误"
        case score < 60:
            g = "不及格"
        case score < 80:
            g = ""
        case score < 90:
            g = ""
        case score <= 100:
            g = "GOOD"
        }
        //default: "hahah"
        return g
    }
    
    func main(){
        fmt.Println(
            grade(0),
            grade(61),
            grade(75),
            grade(86),
            grade(86),
            grade(101),
    
        )
    }

       2.循环结构

        for:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    //死循环
    func for1(){
        for {
            fmt.Println("波多野结衣的奶子大大的")
            //睡一秒
            time.Sleep(1*time.Second)
        }
    }
    
    //有次数的循环
    func for2(){
        for i :=1;i<10;i++ {
            fmt.Println("波多野结衣可以让我幸福死")
        }
    
    }
    
    //有次数的循环加控制
    func for3(){
        for i :=1;i<10;i++{
            if i%5==0{
                fmt.Println("我爱苍老师")
            }else if i%2==1{
                fmt.Println("我爱波多老师")
            }else{
                fmt.Println("我爱大桥未久")
            }
            time.Sleep(1*time.Second)
        }
    }
    
    
    func main(){
        //for1()
        //for2()
        for3()
    }

        range:

    package main
    
    import "fmt"
    
    func main(){
        s :="abc"
        for i :=range s{
            fmt.Printf("下标%d,值=%c
    ",i,s[i])
        }
    
        //直接都收到
        for i,c :=range s{
            fmt.Printf("下标%d,值=%c
    ",i,c)
        }
    
        for _,c :=range s{
            fmt.Printf("值=%c
    ",c)
        }
    }

       3.跳转语句

        continue和break

    package main
    
    import "fmt"
    
    func main(){
        for  i :=0;i<5;i++{
            if i==2{
                //break是直接打断,continue,跳过
                //break
                //continue
    
            }
            fmt.Println(i)
        }
    }

      goto:

    package main
    
    import "fmt"
    
    func main(){
        for i :=1;i<5;i++{
            fmt.Println(i)
            //goto必须跳转到方法内
            goto LABEL2
        }
        fmt.Println("程序结束")
    LABEL2:
        fmt.Println("程序over")
    }

    二.函数

      1.自定义函数

       函数声明格式:
       方法名首字母大写是public,方法名首字母小写是private
      func 函数名( [参数列表] ) [返回值列表] {
         函数体
      }

         分类:

    package main
    
    import "fmt"
    
    
    //无参数无返回值
    func Test1(){
        fmt.Println("公共的")
    }
    
    //有参数无返回值
    func Test2(v1 int,v2 int){
        fmt.Println(v1,v2)
    }
    
    //有不定参数无返回值
    func Test3(args ...int){
        //这边的前面是索引,后面的是值
        for _,n :=range args{
            fmt.Println(n)
        }
    }
    
    //无参数有返回值
    func Test4()(a int,str string){
        a=666
        str="喜欢骑苍老师"
        return
    }
    
    func Test5()(int,string){
        return 250,"喜欢被苍老师骑"
    }
    
    //有参数有返回值(求两个数的最大值和最小值)
    func Test6(num1 int,num2 int)(min int,max int){
        if num1>num2{
            min=num2
            max=num1
        }else{
            min=num1
            max=num2
        }
        return
    
    
    
    }
    func main(){
        Test1()
        Test2(1,2)
        Test3()
        Test3(1,2,3,4)
        fmt.Println(Test4())
        fmt.Println(Test5())
        fmt.Println(Test6(2,1))
    }

       例题:求1.。。100的和

    package main
    
    import "fmt"
    
    // 循环实现1到100累加
    func Test01() int {
       sum := 0
       for i := 1; i <= 100; i++ {
          sum += i
       }
       return sum
    }
    
    //递归实现
    //传100
    func Test02(num int) int {
       if num == 1 {
          return 1
       }
       return num + Test02(num-1)
    }
    
    func main() {
       fmt.Println(Test01())
       fmt.Println(Test02(100))
    }

       2.defer关键字,延迟操作

      

        defer⽤于延迟一个函数或者方法的执行
        defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁
        通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放
        释放资源的defer应该直接跟在请求资源的语句后,以免忘记释放资源
    package main
    
    import "fmt"
    
    func test(x int) {
        fmt.Println(100 / x)
    }
    
    func main() {
        //defer是延迟操作
        defer fmt.Println("aaaa")
        defer fmt.Println("bbbb")
        //报错并不影响程序运行
        defer test(0)
        defer fmt.Println("cccc")
    }

       三.复合类型

      1.指针

        go语言中指针是很容易学习的,比C中容易的多,它可以更简单地执行一些任务
        与变量类似,使用前需要声明
        声明指针的格式: 
    var 指针变量名 *指针类型

      

      简单使用:

    package main
    
    import "fmt"
    
    func main(){
    
        //声明变量
        var a int=10
        //声明指针
        var p *int
        //指针变量储存
        p=&a
        fmt.Printf("a变量的地址是%x
    ",&a)
        //指针变量的存储地址
        fmt.Printf("p变量的指针地址%x
    ",p)
        //使用指针访问值
        fmt.Printf("*p变量的值是:%d
    ",*p)
    
    
    }

      使用指针改变所指向的内存的值

    package main
    
    import "fmt"
    
    func main(){
        //定义变量
        var num int=10
        fmt.Println(&num)
        //定义指针
        var prt *int
        //g给指针赋值(指针指向哪个内存地址)
        prt=&num
        *prt=20
        fmt.Println(num) //20
    }

       

      值传递和引用传递

      go空指针,go空是用nil
    
    

      

    答案  3,4
    

      再看几个例子

    package main
    
    import "fmt"
    
    
    //变量交换
    //go方法是值传递
    func swap(a,b int){
    	a,b =b,a
    }
    
    func main(){
    	a,b :=3,4
    	swap(a,b)
    	fmt.Println(a,b)
    }
    

      答案是3,4

    package main
    
    import "fmt"
    
    
    //go方法参数是值传递
    func swap(a,b *int){
    	*a,*b =*b,*a
    }
    
    func main()  {
    	a,b :=3,4
    	//指针是存地址的
    	swap(&a,&b)
    	fmt.Println(a,b)
    
    }
    

      答案是:4,3

      另一种方法

    package main
    
    import "fmt"
    
    
    //go方法参数是值传递
    func swap(a,b int)(int,int){
    	return b,a
    }
    
    func main()  {
    	a,b :=3,4
    	//指针是存地址的
    	a,b=swap(a,b)
    	fmt.Println(a,b)
    
    }
    

      

      2.new和make

        new()用来分配内存,但与其他语言中的同名函数不同,它不会初始化内存,只会将内存置零
        make(T)会返回一个指针,该指针指向新分配的,类型为T的零值,适用于创建结构体
        make()的目的不同于new(),它只能创建slice、map、channel,并返回类型为T(非指针)的已初始化(非零值)的值

       看一个例子

    package main
    
    import (
        "fmt"
    )
    
    func main(){
        //未初始化
        p :=new([] int)
        fmt.Println(p)
    
    
        //已经初始化
        v:=make([] int,10,50)
        fmt.Println(v)
    
        //*p[0]=10  会报错,下标越界,未初始化为分配
    
        v[0]=10
        fmt.Print(v)
    
    }

       

      3.数组

        声明数组:
    var 数组名[数组长度] 数组类型
        声明和初始化数组
        数组遍历
        数组是值类型还是引用类型?

      看一个例子

    package main
    
    import "fmt"
    
    func main(){
        //1.定义数组
        //数组必须制定长度和类型
        var arr1[5] int
    
        //:=创建,必须赋值
        arr2:=[3] int{1,2,3}
    
        //3省累大小
        arr3 :=[...]int{2,3,4,5,}
        fmt.Println(arr1,arr2,arr3)
    
        var grid[ 4][5]int
        fmt.Println(grid)
    
        //数组遍历
        //1.直接遍历
        for i:=0;i<len(arr3);i++{
            fmt.Println(arr3[i])
        }
    
        //2.range
        for i,v:=range arr3{
            fmt.Println(i,v)
        }
    }

      数组是值传递还是引用传递

    package main
    
    import "fmt"
    
    func main(){
        //1.定义数组
        //数组必须制定长度和类型
        var arr1[5] int
    
        //:=创建,必须赋值
        arr2:=[3] int{1,2,3}
    
        //3省累大小
        arr3 :=[...]int{2,3,4,5,}
        fmt.Println(arr1,arr2,arr3)
    
        var grid[ 4][5]int
        fmt.Println(grid)
    
        //数组遍历
        //1.直接遍历
        for i:=0;i<len(arr3);i++{
            fmt.Println(arr3[i])
        }
    
        //2.range
        for i,v:=range arr3{
            fmt.Println(i,v)
        }
    }

      

       数组和列表的区别,有类型,有大小,不可变

      使用指针

    package main
    
    import "fmt"
    
    //方法传入数组,修改元素
    func printArr(arr *[5] int){
        arr[0]=100
        for i,v:=range arr{
            fmt.Println(i,v)
        }
    }
    
    func main(){
        //定义数组
        var arr1 [5]int
        arr2 := [3]int{1, 2, 3}
        arr3 := [...]int{2, 4, 6, 8, 10}
        fmt.Println(arr1, arr2, arr3)
    
        printArr(&arr1)
        //不同长度,不能传参
        //printArr(arr2)
        printArr(&arr3)
        fmt.Println()
        fmt.Println(arr1, arr3)
    
    }

      

       说明是值传递

      4.slice

        数组的长度在定义之后无法再次修改,go语言提供了数组切片(slice)来弥补数组的不足
        创建切片的各种方式
        切片的操作
        内建函数append()
        内建函数copy()

       切片的创建

    package main
    
    import "fmt"
    
    func main(){
        //声明切片和数组不一样的是不用指定大小
        var s1 []int
        fmt.Println(s1)
        //:声明,必须{},:声明的必须赋值
        s2:=[] int{}
        fmt.Println(s2)
        //make
        //诺写一个0.则代表大小和容量都是0
        //var s3 [] int=make([] int,0)
        //d声明的时候大小为10,存11个也没问题
        var s3 [] int=make([] int,10,10)
        fmt.Println(s3)
    
        s4 := []int{1, 2, 3}
        fmt.Println(s4)
    
    
    
    }

      切片的操作(取值)

    package main
    
    import "fmt"
    
    func main(){
        //其切片取值
        arr :=[...]int{1,2,3,4,5,6,7}
        fmt.Println("arr[2:6]=",arr[2:6])
        fmt.Println("arr[:6]=",arr[:6])
        fmt.Println("arr[2:]=",arr[2:])
        fmt.Println("arr[:]=",arr[:])
    
    
    }

        

       

           内建函数append():向切片尾部添加数据

    package main
    
    import "fmt"
    
    func main(){
        var s1 [] int
        s1=append(s1,1)
        fmt.Println(s1)
    
        s1=append(s1,2,3)
        fmt.Println(s1)
    
        s1=append(s1,4,5,6)
        fmt.Println(s1)
    
    
        //创建指定大小的切片
        s2:=make([] int,5)
        s2=append(s2,6)
        fmt.Println(s2)
    
        //创建并初始化切片
        s3:=[]int{1,2,3}
        s3=append(s3,4)
        fmt.Println(s3)
    
    }

    //从这个例子也能看出数组和切片的区别

      

          go语言切片实际上是view操作

    package main
    
    import "fmt"
    
    func main() {
        //1.go语言切片是对原数组的映射,并没有创建一个真正的切片
        // 定义数组
        arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
        //取切片
        s1 := arr[2:]
        //修改值
        s1[0] = 100
        fmt.Println(s1)
        fmt.Println(arr)
        fmt.Println()
    
        // go语言切片没有取到的位置,可以向后延申,不可向前延申
        s3 := arr[2:6]
        fmt.Println(s3)
        s4 := s3[3:5]
        fmt.Println(s4)
    
        //容量和大小
        fmt.Printf("s3=%v,len(s3)=%d,cap(s3)=%d
    ", s3, len(s3), cap(s3))
    
    }

      

      append操作切片

    package main
    
    import "fmt"
    
    func main() {
       //1.go语言切片是对原数组的映射,并没有创建一个真正的切片
       // 定义数组
       arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
       //取切片
       s1 := arr[2:6]
       fmt.Println(s1)
    
       s2 := s1[3:5]
       fmt.Println(s2)
    
       s3 := append(s2,10)
       fmt.Println(s3)
       fmt.Println(arr)
    
       s4 := append(s3,11)
       fmt.Println(s4)
       fmt.Println(arr)
       s5 := append(s4,12)
       fmt.Println(s5)
       fmt.Println(arr)
    }

      

      5.map

        Map 是go内置的数据结构,是一种无序的键值对的集合,可以通过key快速找到value的值
        定义Map:
    var 变量名 map[key的数据类型] value的数据类型
        创建map
        初始化map
        键值操作
        遍历
        删除
        练习,创建5个方法,创建map,遍历map,删除键值对,修改map,map查询

      6.结构体

        go语言没有class,只是个结构体struct
        结构体定义:
    type 结构体名 struct{}
        结构体初始化

      7.结构体参数

        结构体可以作为函数参数传递

    四.面向对象

      1.简介

    go语言对于面向对象的设计非常简洁而优雅
    没有封装、继承、多态这些概念,但同样通过别的方式实现这些特性

      2.匿名字段

        go支持只提供类型而不写字段名的方式,也就是匿名字段,也称为嵌入字段
        同名字段的情况
        所有的内置类型和自定义类型都是可以作为匿名字段去使用
        指针类型匿名字段

      3.方法

        在面向对象编程中,一个对象其实也就是一个简单的值或者一个变量,在这个对象中会包含一些函数
        这种带有接收者的函数,我们称为方法,本质上,一个方法则是一个和特殊类型关联的函数
        方法的语法如下
    func (接收参数名 接收类型) 方法名(参数列表)(返回值)
        可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法
        接收类型可以是指针或非指针类型
        为类型添加方法
        值语义和引用语义
        方法的继承
        方法的重写
        方法值和方法表达式
        练习:创建属性的getter和setter方法并进行调用

      4.  包和封装

        方法首字母大写:public
        方法首字母小写:private
        为结构体定义的方法必须放在同一个包内,可以是不同的文件

      5.接口

        go语言中,接口(interface)是一个自定义类型,描述了一系列方法的集合
        接口不能被实例化
        接口定义语法如下
    type 接口名 interface{}
        PS:接口命名习惯以er结尾
        接口定义与实现
        接口继承
        空接口
        类型查询
        comma-ok断言
        switch测试

      6.面向对象练习

        定义接口IPerson,定义吃喝睡三个抽象方法
        定义结构体Person,实现上述方法
        定义一个Person的实现类Worker即劳动者,拥有劳动方法Work()(output string)其中output是其工作产出,和休息方法Rest()
        继承IWorker实现三个不同职业的子类:程序员Coder、老师Teacher、农民Farmer
        创建一个IWorker的数组,将3个实例添加进去
        main中测试工作日和周末,输出如下打印

    五.异常处理 

      1.抛异常和处理异常

    系统抛
    自己抛

      2.返回异常

    六.处理字符串

     

  • 相关阅读:
    golng切片实现分页
    go mgo包 简单封装 mongodb 数据库驱动
    docker 制作自己的镜像
    mongodb 数据库操作——备份 还原 导出 导入
    Override
    Parallel.For循环与普通的for循环的比较
    C#死锁案例代码
    C#的构造函数在基类和父类中执行顺序
    C#构造函数
    C# 多线程的死锁
  • 原文地址:https://www.cnblogs.com/tjp40922/p/10802424.html
Copyright © 2011-2022 走看看