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\n",content)
    }

    //if也支持如下语法
    if content,err :=ioutil.ReadFile(filename);err !=nil{
        fmt.Println(err)
    }else{
        fmt.Printf("%s\n",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\n",i,s[i])
    }

    //直接都收到
    for i,c :=range s{
        fmt.Printf("下标%d,值=%c\n",i,c)
    }

    for _,c :=range s{
        fmt.Printf("值=%c\n",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\n",&a)
    //指针变量的存储地址
    fmt.Printf("p变量的指针地址%x\n",p)
    //使用指针访问值
    fmt.Printf("*p变量的值是:%d\n",*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\n", 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.返回异常

六.处理字符串

 

posted @ 2019-05-02 15:26  阿布_alone  阅读(237)  评论(0编辑  收藏  举报
TOP