zoukankan      html  css  js  c++  java
  • Go语言学习之3 流程控制、函数

    主要内容:

    1. strings和strconv使用
    2. Go中的时间和日期类型
    3. 指针类型
    4. 流程控制
    5. 函数详解

    1. strings和strconv使用

    //strings
    1. strings.HasPrefix(s string, prefix string) bool:判断字符串s是否以prefix开头 。
    2. strings.HasSuffix(s string, suffix string) bool:判断字符串s是否以suffix结尾。
    3. strings.Index(s string, str string) int:判断str在s中首次出现的位置,如果没有
    4. strings.LastIndex(s string, str string) int:判断str在s中最后出现的位置,如果没有
    5. strings.Replace(str string, old string, new string, n int)string:字符串替换
    6. strings.Count(str string, substr string)int:字符串计数
    7. strings.Repeat(str string, count int)string:重复count次str
    8. strings.ToLower(str string)string:转为小写
    9. strings.ToUpper(str string)string:转为大写
    10. strings.TrimSpace(str string) string:去掉字符串首尾空白字符
        strings.Trim(str string, cut string) string:去掉字符串首尾cut字符
        strings.TrimLeft(str string, cut string) string:去掉字符串首cut字符
        strings.TrimRight(str string, cut string) string:去掉字符串首cut字符
    11. strings.Fields(str string) []string:返回str空格分隔的所有子串的slice
        strings.Split(str string, split string) []string:返回str split分隔的所有子串的slice
    12. strings.Join(s1 []string, sep string) string:用sep把s1中的所有元素链接起来
    
    //strconv
    13. strconv.Itoa(i int) string:把一个整数i转成字符串
    14. strconv.Atoi(str string)(int, error):把一个字符串转成整数

    例子:

      1 package main 
      2 
      3 import (
      4     "fmt"
      5     "strings"
      6     "strconv"
      7 )
      8 
      9 func main() {
     10     var res bool
     11     //HasPrefix
     12     res = strings.HasPrefix("https://www.baidu.com", "https://") //true
     13     fmt.Printf("%v
    ", res)
     14     res = strings.HasPrefix("https://www.baidu.com", "albaba") //false
     15     fmt.Printf("%v
    ", res)
     16 
     17     //HasSuffix
     18     res = strings.HasSuffix("/root/temp/", "/") //true
     19     fmt.Printf("%v
    ", res)
     20     res = strings.HasSuffix("/root/temp/", "=") //false
     21     fmt.Printf("%v
    ", res)
     22 
     23     var result int
     24     //Index
     25     result = strings.Index("hahahelloworld", "he") //4
     26     fmt.Printf("%v
    ", result)
     27     
     28     //LastIndex
     29     result = strings.LastIndex("hahahelloworldhe", "he") //14
     30     fmt.Printf("%v
    ", result)
     31 
     32     var result2 string
     33     //Replace
     34     result2 = strings.Replace("hahahelloworldhe", "ha", "HA", 1) //HAhahelloworldhe
     35     fmt.Printf("%v
    ", result2)
     36     result2 = strings.Replace("hahahelloworldhe", "ha", "HA", -1) //HAHAhelloworldhe
     37     fmt.Printf("%v
    ", result2)
     38 
     39     //Count
     40     result = strings.Count("hahahelloworldhe", "ha") //2
     41     fmt.Printf("%v
    ", result)
     42 
     43     //Repeat
     44     result2 = strings.Repeat("ha", 3) //hahaha
     45     fmt.Printf("%v
    ", result2)
     46     
     47     //ToLower
     48     result2 = strings.ToLower("heLLo") //hello
     49     fmt.Printf("%v
    ", result2)
     50 
     51     //ToUpper
     52     result2 = strings.ToUpper("hello") //HELLO
     53     fmt.Printf("%v
    ", result2)
     54 
     55     //TrimSpace
     56     result2 = strings.TrimSpace("   hello   ") //hello
     57     fmt.Printf("%v
    ", result2)
     58 
     59     //Trim
     60     result2 = strings.Trim("123hello123", "123") //hello
     61     fmt.Printf("%v
    ", result2)
     62 
     63     //TrimLeft
     64     result2 = strings.TrimLeft("123hello123", "123") //hello123
     65     fmt.Printf("%v
    ", result2)
     66 
     67     //TrimRight
     68     result2 = strings.TrimRight("123hello123", "123") //123hello
     69     fmt.Printf("%v
    ", result2)
     70 
     71     var result3 []string
     72     //Fields
     73     result3 = strings.Fields("root temp work")
     74     for i := 0; i < len(result3); i++ {
     75         fmt.Printf("%v
    ", result3[i])
     76     }
     77     
     78     //Split
     79     result3 = strings.Split("/root/temp/work", "/")
     80     for i := 0; i < len(result3); i++ {
     81         fmt.Printf("%v
    ", result3[i])
     82     }
     83 
     84     //Join
     85     result3 = [] string{"root", "temp", "work"}
     86     result2 = strings.Join(result3, "/") // root/temp/work
     87     fmt.Println(result2)
     88 
     89     //Itoa
     90     num := 123
     91     result2 = strconv.Itoa(num) // root/temp/work
     92     fmt.Printf("%s
    ", result2) // 123
     93 
     94     //Atoi
     95     str := "12345"
     96     number, err := strconv.Atoi(str) // root/temp/work
     97     if err != nil {
     98         fmt.Printf("Can not convert %s to int
    ", str)
     99         return
    100     }
    101     fmt.Printf("%d
    ", number) // 12345
    102 }
    example

    练习1:判断一个url是否以http://开头,如果不是,则加上http://。
    练习2:判断一个路径是否以"/"结尾,如果不是,则加上/。

     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "strings"
     6 )
     7 
     8 func urlProcess(url string) string {
     9     res := strings.HasPrefix(url, "http://")
    10     if !res {
    11         url = fmt.Sprintf("http://%s", url)
    12     }
    13     return url
    14 }
    15 
    16 func pathProcess(path string) string {
    17     res := strings.HasSuffix(path, "/")
    18     if !res {
    19         path = fmt.Sprintf("%s/", path)
    20     }
    21     return path
    22 }
    23 
    24 func main() {
    25     var (
    26         url string
    27         path string        
    28     )
    29 
    30     fmt.Println("Input url and path >>")
    31     fmt.Scanf("%s%s", &url, &path)
    32 
    33     url = urlProcess(url)
    34     path = pathProcess(path)
    35 
    36     fmt.Println("url: ", url)
    37     fmt.Println("path: ", path)
    38 }
    练习1和2

    练习3:写一个函数返回一个字符串在另一个字符串的首次出现和最后出现位置。

     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "strings"
     6 )
     7 
     8 func strIndex(str string, substr string)(int, int) {
     9     var startIndex, endIndex int
    10 
    11     startIndex = strings.Index(str, substr)
    12     endIndex = strings.LastIndex(str, substr)
    13 
    14     return startIndex, endIndex
    15 }
    16 
    17 func main() {
    18     var str, substr string
    19     fmt.Println("Input a string >> ")
    20     fmt.Scanf("%s%s", &str, &substr)
    21 
    22     start, end := strIndex(str, substr)
    23     if start < 0 {
    24         fmt.Printf("Can not find %s in %s.
    ", substr, str)
    25     } else {
    26         fmt.Printf("First find %s in %s %d index.
    ", substr, str, start)
    27     }
    28 
    29     if end < 0 {
    30         fmt.Printf("Can not find %s in %s.
    ", substr, str)
    31     } else {
    32         fmt.Printf("Last find %s in %s %d index.
    ", substr, str, end)
    33     }
    34 }
    练习3

    练习4:写一个函数分别演示Replace、Count、Repeat、ToLower、ToUpper的用法。
    练习5:写一个函数分别演示TrimSpace、Trim、TrimLeft、TrimRight、Field、Split、以及Join的用法。
    练习6:写一个函数分别演示Itoa、Atoi的用法。

    2. Go中的时间和日期类型

    1. time包
    2. time.Time类型,用来表示时间
    3. 获取当前时间, now := time.Now()
    4. time.Now().Day(),time.Now().Minute(),time.Now().Month(),time.Now().Year()
    5. 格式化,fmt.Printf("%02d/%02d%02d %02d:%02d:%02d", now.Year()…)
    6. time.Duration用来表示纳秒
    7. 一些常量:
        const (
             Nanosecond Duration = 1
             Microsecond = 1000 * Nanosecond
             Millisecond = 1000 * Microsecond
             Second = 1000 * Millisecond
             Minute = 60 * Second
             Hour = 60 * Minute
        )
    8. 格式化:
        now := time.Now()
        fmt.Println(now.Format(“02/1/2006 15:04”))
        fmt.Println(now.Format(“2006/1/02 15:04”))
        fmt.Println(now.Format(“2006/1/02”))

    练习6:写一个程序,获取当前时间,并格式化成 2017/06/15 08:05:00形式。

     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "time"
     6 )
     7 
     8 func main() {
     9     now := time.Now()
    10     fmt.Println(now.Format("02/1/2006 15:04")) // 12/2/2019 18:13
    11     fmt.Println(now.Format("2006/1/02 15:04")) // 2019/2/12 18:13
    12     fmt.Println(now.Format("2006/1/02")) // 2019/2/12
    13 }
    练习6

    练习7:写一个程序,统计一段代码的执行耗时,单位精确到微秒。

     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "time"
     6 )
     7 
     8 func costTime() {
     9     for i := 0; i < 100000000; i++ {
    10 
    11     }
    12 }
    13 
    14 func main() {
    15     start := time.Now().UnixNano() // ns
    16     costTime()
    17     end := time.Now().UnixNano()
    18 
    19     fmt.Printf("cost:%d us
    ", (end-start)/1000)
    20 }
    练习7

    3. 指针类型

    1. 普通类型,变量存的就是值,也叫值类型
    2. 获取变量的地址,用&,比如: var a int, 获取a的地址:&a
    3. 指针类型,变量存的是一个地址,这个地址存的才是值
    4. 获取指针类型所指向的值,使用:*,比如:var *p int, 使用*p获取p指向的值

    练习8:写一个程序,获取一个变量的地址,并打印到终端。
    练习9:写一个函数,传入一个int类型的指针,并在函数中修改所指向的值。在main函数中调用这个函数,并把修改前后的值打印到终端,观察结果。

     1 package main 
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func test(num int) {
     8     fmt.Printf("In the test add %v
    ", &num)
     9 }
    10 
    11 func changeNum(num *int) {
    12     *num = 100
    13 }
    14 
    15 func main() {
    16     var num int = 10
    17     fmt.Printf("In the main add %v
    ", &num) //In the main add 0xc04203c1d0
    18     test(num) // In the test add 0xc04203c1d8
    19     fmt.Printf("num = %d
    ", num)  // num = 10
    20     changeNum(&num)
    21     fmt.Printf("num = %d
    ", num) //num = 100
    22 }
    练习8和9

    4. 流程控制

    1. If / else分支判断

    单个分支

    if condition1 {
    }

    两个分支

    if condition1 {    
    } else {
    }

    多个分支

    if condition1 {
    } else if condition2 {
    } else if condition3 {
    } else {
    }

    注意:下面这种写法是错误的

    if condition1 {
    }
    else {
    }

    练习10:写一个程序,从终端读取输入,并转成整数,如果转成整数出错,则输出 "can not convert to int",并返回。否则输出该整数。

     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "strconv"
     6 )
     7 
     8 func main() {
     9     var str string
    10     fmt.Println("Input a number >>")
    11     fmt.Scanf("%s", &str)
    12     number, err := strconv.Atoi(str)
    13     if err != nil {
    14         fmt.Printf("Can not convert %s to int
    ", str)
    15         return
    16     }
    17     fmt.Printf("%d", number)
    18 }
    练习10

    2. switch case语句
    语法:
           switch var {
               case var1:
               case var2:
               case var3:
               default:
           }

    特别注意:go语言中和C语言不一样,在case后面没有break语句。

     1 switch var {
     2            case var1:
     3                 {
     4                     语句
     5                     break;
     6                 }
     7                 
     8            case var2:
     9                 {
    10                     语句
    11                     break;
    12                 }
    13            case var3:
    14                 {
    15                     语句
    16                     break;
    17                 }
    18            default:
    19                     语句
    20        }
    C语言写法

    写法1:

    var num int = 2
    switch num {
        case 0:
            fmt.Println("0")
        case 1:
            fmt.Println("1")
        case 2:
            fmt.Println("2")
        default:
            fmt.Printf("%d
    ", num)
    }

    写法2:跨越case的fallthrough

    var i = 0
    switch i {
    case 0:
        fmt.Println("0") // 会执行
        fallthrough
    case 1:
        fmt.Println("1") // 由于上面fallthrough 所以会执行
    case 2:
        fmt.Println("2")
    default:
         fmt.Println("default")
    }

    注意:加上fallthrough则当前case语句执行完成之后会紧接着执行相邻的第一条case。

    写法3:

    var i = 0
    switch i {
       //两个case合并
        case 0, 1:
            fmt.Println("0 or 1")
        case 2:
            fmt.Println("2")
        default:
            fmt.Println("def")
    }

    写法4:

    var i = 0
    switch {
        case i > 0 && i < 10:
            fmt.Println("i > 0 and i < 10")
        case i >= 10 && i < 20:
            fmt.Println("i > 10 and i < 20")
        default:
            fmt.Println("default")
    }

    写法5:

    switch i := 15; {
        case i > 0 && i < 10:
            fmt.Println("i > 0 and i < 10")
        case i >= 10 && i < 20:
            fmt.Println("i > 10 and i < 20")
        default:
            fmt.Println("def")
    }

    注意: i := 15; 后面的分号(;)

     练习11:猜数字,写一个程序,随机生成一个0到100的整数n,然后用户在终端,输入数字,如果和n相等,则提示用户猜对了。如果不相等,则提示用户,大于或小于n。

     1 package main
     2 
     3 import (
     4     "fmt"
     5     "math/rand"
     6 )
     7 
     8 func main() {
     9     var n int
    10     n = rand.Intn(100)
    11 
    12     for {
    13         var input int
    14         fmt.Println("Input your guess >> ")
    15         //注意后面的
    作用,如果没有的话,则输入的数和
    16         fmt.Scanf("%d
    ", &input)
    17         flag := false
    18         switch {
    19         case input == n:
    20             fmt.Println("you are right")
    21             flag = true
    22         case input > n:
    23             fmt.Println("bigger")
    24         case input < n:
    25             fmt.Println("less")
    26         }
    27 
    28         if flag {
    29             break
    30         }
    31     }
    32 }
    练习11

    3. for 语句

    写法1:

    for 初始化语句; 条件判断; 变量修改 {
    }
    //例如
    for i := 0; i < 100; i++ {
        fmt.Printf("i=%d
    ", i)
    }

    练习12:写一个程序,在终端打印如下图形。

    A
    AA
    AAA
    AAAA
    AAAAA
     1 package main 
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     var row int
     9     fmt.Println("Input row number >>")
    10     fmt.Scanf("%d", &row)
    11     for i := 0; i < row; i++ {
    12         for j := 0; j <= i; j++ {
    13             fmt.Printf("A")
    14         }
    15         fmt.Println()
    16     }
    17 }
    练习12

    写法2:

    for  条件 {
    }

    例如:下面三个条件为真都是死循环

    for i > 0 {
        fmt.Println("i > 0")
    }
    
    for true {
        fmt.Println("i > 0")
    }
    
    for {
        fmt.Println("i > 0")
    }

    4. for range 语句

    写法3:用来遍历数组、slice、map、chan

    str := "hello world,中国" //汉字占3个字节
        for i, v := range str {
            fmt.Printf("index = %d val = %c byteLen = %d
    ", i, v, len([] byte(string(v))))
        }

    5. break、continue语句

    package main
    
    import "fmt"
    
    func main() {
        str := "hello world,中国"
        for i, v := range str {
            if i > 2 {
                continue
            }
            if (i > 3) {
                break  
            }
        
            fmt.Printf("index[%d] val[%c] len[%d]
    ", i, v, len([]byte(string(v))))
        }
    }
    
    //输出:
    //index[0] val[h] len[1]
    //index[1] val[e] len[1]
    //index[2] val[l] len[1]

    break 语句可以结束 for、switch 和 select 的代码块。break 语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的 for、switch 和 select 的代码块上。例如:

    package main
    import "fmt"
    func main() {
    OuterLoop:
        for i := 0; i < 2; i++ {
            for j := 0; j < 5; j++ {
                switch j {
                case 2:
                    fmt.Println(i, j)
                    break OuterLoop
                case 3:
                    fmt.Println(i, j)
                    break OuterLoop
                }
            }
        }
    }
    
    //输出 说明第10行的break OuterLoop直接跳出外层循环
    //0 2

    continue 语句可以结束当前循环,开始下一次的循环迭代过程,仅限在 for 循环内使用。在 continue 语句后添加标签时,表示开始标签对应的循环。例如:

    package main
    import "fmt"
    func main() {
    OuterLoop: //代码说明:第 10 行将结束当前循环,开启下一次的外层循环,而不是第 10 行的内循环。
        for i := 0; i < 2; i++ {
            for j := 0; j < 5; j++ {
                switch j {
                case 2:
                    fmt.Println(i, j)
                    continue OuterLoop
                }
            }
        }
    }
    
    //输出:
    //0 2
    //1 2

    6. goto 和 label 语句

    goto 语句通过标签进行代码间的无条件跳转。goto 语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go 语言中使用 goto 语句能简化一些代码的实现过程。

    package main
    
    func main() {
        i := 0
    HERE:
        print(i)
        i++
        if i == 5 {
            return
        }
        goto HERE
    }
    
    //输出:
    //01234

     5. 函数

    1. 声明语法:func 函数名 (参数列表) [(返回值列表)] {}

    //无参数,无返回值
    func add() {
    }
    
    //有参数,无返回值
    func add(a int, b int) {
    }
    
    //有参数,一个返回值
    func add(a int, b int) int {
    }
    
    //有参数,两个返回值
    func add(a int, b int) (int, int) {
    }
    
    //有参数,两个返回值
    func add(a, b int) (int, int) {
    }

    2. golang函数特点:
        a. 不支持重载,一个包不能有两个名字一样的函数
        b. 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量

     1 package main
     2 
     3 import "fmt"
     4 
     5 func add(a, b int) int {
     6     return a + b
     7 }
     8 
     9 func main() {
    10     c := add  //将函数add的地址赋值给变量c
    11     fmt.Println(c) //0x4888e0
    12 
    13     sum := c(10, 20)
    14     fmt.Println(sum)
    15     // if (c == add) {  //invalid operation: c == add (func can only be compared to nil)
    16     //     fmt.Println("c equal add")
    17     // }
    18 }
    函数赋值给变量

        c. 匿名函数

     1 package main
     2 
     3 import "fmt"
     4 
     5 var (
     6     //add存放的是匿名函数的地址
     7     add = func(a int, b int) int {
     8         return a + b
     9     }
    10     
    11     //sub_res存放的是匿名函数执行的结果100
    12     sub_res = func(a int, b int) int {
    13         return a - b
    14     }(200, 100) 
    15 )
    16 
    17 func test(a, b int) int {
    18     //mult存放的是匿名函数的地址
    19     mult := func(m int, n int) int {
    20         return m*n
    21     }
    22     return mult(a, b)
    23 }
    24 
    25 func main() {
    26     fmt.Println(add(100, 200))  //300
    27     fmt.Println(sub_res)  //100
    28         fmt.Println(test(200, 300))  //60000
    29 }
    匿名函数

        d. 多返回值

    使用type定义函数类型: type type_name func 函数名 (参数列表) [(返回值列表)],例如:

     1 package main
     2 
     3 import "fmt"
     4 
     5 //定义函数类型
     6 type add_func func(int, int) int
     7 
     8 func add(a, b int) int {
     9     return a + b
    10 }
    11 
    12 // error 因为上面定义的函数类型add_func接收两个参数,下面定义三个参数。
    13 // func add(a, b, c int) int {
    14 //     return a + b
    15 // }
    16 
    17 func sub(a, b int) int {
    18     return a - b
    19 }
    20 
    21 func operator(op add_func, a int, b int) int {
    22     return op(a, b)
    23 }
    24 
    25 func main() {
    26     c := add
    27     fmt.Println(c)
    28     sum := operator(c, 100, 200)
    29     fmt.Println(sum)  //300
    30 
    31     res := operator(sub, 100, 200)
    32     fmt.Println(res)  //-100
    33 }
    定义函数类型

    3. 函数参数传递方式:
        1). 值传递
        2). 引用传递
        注意1:无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决                   于拷贝的对象大小,对象越大,则性能越低。
        注意2:map、slice、chan、指针、interface默认以引用的方式传递。

    4. 命名返回值的名字

     1 package main 
     2 
     3 import "fmt"
     4 
     5 func add(a, b int) (sum int) {
     6     sum = a + b
     7     return
     8 }
     9 
    10 // 等价于
    11 // func add(a, b int) int {
    12 //     sum = a + b
    13 //     return sum
    14 // }
    15 
    16 func calc(a, b int) (sum int, avg int) {
    17     sum = a + b
    18     avg = (a +b)/2
    19     return
    20 }
    21 
    22 // 等价于
    23 // func calc(a, b int) (int, int) {
    24 //     sum = a + b
    25 //     avg = (a +b)/2
    26 //     return sum, avg
    27 // }
    28 
    29 
    30 func main() {
    31     add_res := add(100, 200)
    32     fmt.Println(add_res) //300
    33     sum, avg := calc(100, 200)
    34         fmt.Println(sum) //300
    35         fmt.Println(avg) //150
    36 }
    命名返回值的名字

    5. _标识符,用来忽略返回值

     1 package main 
     2 
     3 import "fmt"
     4 
     5 func calc(a, b int) (sum int, avg int) {
     6     sum = a + b
     7     avg = (a +b)/2
     8     return
     9 }
    10 
    11 func main() {
    12     sum, _ := calc(100, 200)
    13     fmt.Println(sum) //300
    14 }
    忽略返回值

    6. 可变参数

    注意:其中arg是一个slice,通过len(arg)来判断传递参数的个数,通过arg[index]依次访问所有参数。

    //0个或多个参数
    func add(arg…int) int {
    }
    
    //1个或多个参数
    func add(a int, arg…int) int {
    }
    
    //2个或多个参数
    func add(a int, b int, arg…int) int {
    }

    练习14:写一个函数add,支持1个或多个int相加,并返回相加结果。
    练习15:写一个函数concat,支持1个或多个string相拼接,并返回结果。

     1 package main
     2 
     3 import "fmt"
     4 
     5 func add(a int, arg ...int) int {
     6     var sum int = a
     7     for i := 0; i < len(arg); i++ {
     8         sum += arg[i]
     9     }
    10 
    11     return sum
    12 }
    13 
    14 func concat(a string, arg ...string) (result string) {
    15     result = a
    16     for i := 0; i < len(arg); i++ {
    17         result += arg[i]
    18     }
    19 
    20     return
    21 }
    22 
    23 func main() {
    24     sum := add(10, 3, 3, 3, 3)
    25     fmt.Println(sum) //22
    26 
    27     res := concat("hello", " ", "world")
    28     fmt.Println(res) //hello world
    29 }
    可变参数

    7. defer用途
        1). 当函数返回时,执行defer语句。因此,可以用来做资源清理。
        2). 多个defer语句,按先进后出的方式执行。
        3). defer语句中的变量,在defer声明时就决定了。

     1 package main 
     2 
     3 import "fmt"
     4 
     5 func test() {
     6     i := 0
     7     defer fmt.Println(i)
     8     i++
     9     return
    10 } 
    11 
    12 func main() {
    13     test() // 0
    14 }
    example1
     1 package main 
     2 
     3 import "fmt"
     4 
     5  func test() {
     6     for i := 0; i < 5; i++ {
     7         defer fmt.Printf("%d ", i)
     8     } 
     9 } 
    10 
    11 
    12 func main() {
    13     test() // 4 3 2 1 0
    14 }
    example2

    defer几个常用用途:

    (1). 关闭文件句柄

    1 func read() {
    2     file := open(filename)
    3     defer file.Close()
    4     
    5     //文件操作
    6 }
    关闭文件句柄

    (2). 锁资源释放

    1 func read() {
    2     mc.Lock()
    3     defer mc.Unlock()
    4     //其他操作
    5 }
    锁资源释放

    (3). 数据库连接释放

    1 func read() {
    2     conn := openDatabase()
    3     defer conn.Close()
    4     //其他操作
    5 }
    数据库连接释放

    练习:

    1.编写程序,在终端输出九九乘法表。

     1 package main 
     2 
     3 import "fmt"
     4 
     5 func mutil() {
     6     for i := 1; i <= 9; i++ {
     7         for j := 1; j <= i; j++ {
     8             fmt.Printf("%d*%d=%d	", i, j, i*j)
     9         }
    10         fmt.Printf("
    ")
    11     }
    12 }
    13 
    14 func main() {
    15     mutil()
    16 }
    练习1

    2.一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3编程找出1000以内的所有完数。

     1 package main 
     2 
     3 import "fmt"
     4 
     5 func isPerfNum(num int) bool {
     6     res := 0
     7     for i := 1; i < num; i++ {
     8         if num % i == 0 {
     9             res += i
    10         }
    11     }
    12 
    13     return res == num
    14 }
    15 
    16 func process(n int) {
    17     for i := 1; i <= n; i++ {
    18         if isPerfNum(i) {
    19             fmt.Println(i)
    20         } 
    21     }
    22 }
    23 
    24 func main() {
    25     var num int
    26     fmt.Println("Input a number >> ")
    27     fmt.Scanf("%d", &num)
    28     process(num)
    29 }
    练习2

    3.输入一个字符串,判断其是否为回文。回文字符串是指从左到右读和从右到左读完全相同的字符串。

     1 package main 
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func isPalindNum(str string) bool {
     8     flag := true
     9     for i := 0; i <= int(len(str)/2); i++ {
    10         if str[i] != str[len(str)-i-1] {
    11             flag = false
    12             break
    13         }
    14     }
    15 
    16     return flag
    17 }
    18 
    19 func main() {
    20     var str string
    21     fmt.Println("Input a string >> ")
    22     fmt.Scanf("%s", &str)
    23     if isPalindNum(str) {
    24         fmt.Printf("%s is a palindrome number.", str)
    25     }
    26 }
    练习3 V1(无法处理汉字回文数)
     1 package main 
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func isPalindNum(str string) bool {
     8     temp := [] rune(str) //注意这块的处理
     9     flag := true
    10     for i := 0; i <= int(len(temp)/2); i++ {
    11         if temp[i] != temp[len(temp)-i-1] {
    12             flag = false
    13             break
    14         }
    15     }
    16 
    17     return flag
    18 }
    19 
    20 func main() {
    21     var str string
    22     fmt.Println("Input a string >> ")
    23     fmt.Scanf("%s", &str)
    24     if isPalindNum(str) {
    25         fmt.Printf("%s is a palindrome number.", str)
    26     }
    27 }
    练习3 V2(完整版)

    4.输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。

     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "os"
     6     "bufio"
     7 )
     8 
     9 func count(str string) (charCount, spaceCount, numberCount, otherCount int) {
    10     t := [] rune(str)
    11     for _, v := range t {
    12         switch {
    13             case v >= 'A' && v <= 'Z':
    14                 fallthrough
    15             case v >= 'a' && v <= 'z':
    16                 charCount++
    17             case v == ' ':
    18                 spaceCount++
    19             case v >= '0' && v <= '9':
    20                 numberCount++
    21             default:
    22                 otherCount++
    23         }
    24     }
    25     return
    26 }
    27 
    28 
    29 func main() {
    30     reader := bufio.NewReader(os.Stdin)
    31     result, _, err := reader.ReadLine()
    32     if err != nil {
    33         fmt.Println("read from console err:", err)
    34         return
    35     }
    36     cc, sc, nc, oc := count(string(result)) //注意:result为type []byte,因此需要强制转换为string类型
    37     fmt.Printf("charCount = %d, spaceCount = %d, numberCount = %d, otherCount = %d", cc, sc, nc, oc)
    38 }
    练习4

    5. 计算两个大数相加的和,这两个大数会超过int64的表示范围。

      1 package main 
      2 
      3 import (
      4     "fmt"
      5     "os"
      6     "bufio"
      7     "strings"
      8 )
      9 
     10 func add(str1, str2 string) (result string) {
     11     var left int = 0  //进位
     12 
     13     if len(str1) == 0 || len(str2) == 0 {
     14         result = "0"
     15         return
     16     }
     17 
     18     index1 := len(str1) - 1
     19     index2 := len(str2) - 1
     20     //处理重合部分
     21     for index1 >= 0 && index2 >= 0 {
     22         c1 := str1[index1] - '0'
     23         c2 := str2[index2] - '0'
     24 
     25         sum := int(c1) + int(c2) + left
     26         if sum >= 10 {
     27             left = 1
     28         } else {
     29             left = 0
     30         }
     31 
     32         c3 := (sum%10) + '0'
     33         result = fmt.Sprintf("%c%s", c3, result)
     34 
     35         index1--
     36         index2--
     37     }
     38 
     39     //处理str1长度大于str2情况
     40     for index1 >= 0 {
     41         c1 := str1[index1] - '0'
     42 
     43         sum := int(c1) + left
     44         if sum >= 10 {
     45             left = 1
     46         } else {
     47             left = 0
     48         }
     49 
     50         c3 := (sum%10) + '0'
     51         result = fmt.Sprintf("%c%s", c3, result)
     52 
     53         index1--
     54     }
     55 
     56     //处理str1长度小于str2情况
     57     for index2 >= 0 {
     58         c2 := str2[index2] - '0'
     59 
     60         sum := int(c2) + left
     61         if sum >= 10 {
     62             left = 1
     63         } else {
     64             left = 0
     65         }
     66 
     67         c3 := (sum%10) + '0'
     68         result = fmt.Sprintf("%c%s", c3, result)
     69 
     70         index2--
     71     }
     72 
     73     //处理str1长度等于str2情况
     74     if left == 1 {
     75         result = fmt.Sprintf("1%s", result)
     76     }
     77     return
     78 }
     79 
     80 func main() {
     81     fmt.Println("please input a+b >>")
     82     //从console端读取数据
     83     reader := bufio.NewReader(os.Stdin)
     84     result, _, err := reader.ReadLine()
     85     if err != nil {
     86         fmt.Println("read from console err:", err)
     87         return
     88     }
     89     
     90     //获取加数与被加数
     91     strSlice := strings.Split(string(result), "+")
     92     if len(strSlice) != 2 {
     93         fmt.Println("please input a+b")
     94         return
     95     }
     96 
     97     //去除左右空格
     98     str1 := strings.TrimSpace(strSlice[0])
     99     str2 := strings.TrimSpace(strSlice[1])
    100     fmt.Println(add(str1, str2))
    101 }
    练习5

    补充:rune数据类型

    例1:

    1 package main
    2 
    3 import "fmt"
    4 
    5 func main() {
    6 
    7     var str = "hello 你好"
    8     fmt.Println("len(str):", len(str)) //len(str): 12
    9 }
    example

    为何输出12?

    golang中string底层是通过byte数组实现的。中文字符在unicode下占2个字节,在utf-8编码下占3个字节,而golang默认编码是utf-8。因此输出12。

    例2:

     1 package main
     2 
     3 import "fmt"
     4 
     5 func main() {
     6 
     7     var str = "hello 你好"
     8     fmt.Println("len(str):", len(str)) //len(str): 12
     9 
    10     temp := [] rune(str)
    11     fmt.Println("len(temp):", len(temp)) //len(temp): 8
    12 }
    example2

    现在来看rune数据类型官方解释:

     rune is an alias for int32 and is equivalent to int32 in all ways. It is used, by convention, to distinguish character values from integer values.

    rune是int32的别名,几乎在所有方面等同于int32,它用来区分字符值和整数值。type rune = int32。

    如果我们预期想得到一个字符串的长度,而不是字符串底层占得字节长度,该怎么办?

    例3:

     1 package main
     2 
     3 import (
     4     "fmt"
     5     "unicode/utf8"
     6 )
     7 
     8 func main() {
     9 
    10     var str = "hello 你好"
    11     // 方法1:
    12     //golang中的unicode/utf8包提供了用utf-8获取长度的方法
    13     fmt.Println("RuneCountInString:", utf8.RuneCountInString(str))  //RuneCountInString: 8
    14 
    15     //方法2:
    16     //通过rune类型处理unicode字符
    17     temp := [] rune(str)
    18     fmt.Println("rune:", len(temp))  //rune: 8
    19 }
    example3

    例4:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8 
     9     var str = "hello 你好"
    10     for i := 0; i < len(str); i++ {
    11         fmt.Println(str[i])
    12     }
    13 
    14     fmt.Println("--------")
    15 
    16     temp := [] rune(str)
    17     for i := 0; i < len(temp); i++ {
    18         fmt.Println(temp[i])
    19     }
    20 }
    21 
    22 //输出结果
    23 // 104
    24 // 101
    25 // 108
    26 // 108
    27 // 111
    28 // 32
    29 // 228
    30 // 189
    31 // 160
    32 // 229
    33 // 165
    34 // 189
    35 // --------
    36 // 104
    37 // 101
    38 // 108
    39 // 108
    40 // 111
    41 // 32
    42 // 20320
    43 // 22909
    example4

    总结:

    golang中一个byte数据类型与rune相似,它们都是用来表示字符类型的变量类型。它们的不同在于:
    (1). byte 等同于int8,常用来处理ascii字符。
    (2). rune 等同于int32,常用来处理unicode或utf-8字符。

    参考文献:

    • https://www.jianshu.com/p/4fbf529926ca
  • 相关阅读:
    粉丝投稿!从2月份的面试被拒到如今的阿里P7,说一说自己学java以来的经验!
    深入浅出!阿里P7架构师带你分析ArrayList集合源码,建议是先收藏再看!
    简单梳理一下Redis实现分布式Session,建议做java开发的都看看!
    HashMap知识点总结,这一篇算是总结的不错的了,建议看看!
    面试官:小伙子,够了够了,一个工厂模式你都在这说半个小时了!
    iOS-----推送机制(下)
    iOS-----推送机制(上)
    iOS-----使用CoreLocation定位
    iOS-----使用AFNetworking实现网络通信
    iOS-----JSON解析
  • 原文地址:https://www.cnblogs.com/xuejiale/p/10364745.html
Copyright © 2011-2022 走看看