Go語言系列(三)- 基礎函數和流程控制

1、strings和strconv的使用

  • 1. strings.HasPrefix(s string, prefix string) bool:判斷字符串s是否以prefix開頭 。python

  • 2. strings.HasSuffix(s string, suffix string) bool:判斷字符串s是否以suffix結尾。golang

  • 3. strings.Index(s string, str string) int:判斷str在s中首次出現的位置,若是沒有出現,則返回-1數據庫

  • 4. strings.LastIndex(s string, str string) int:判斷str在s中最後出現的位置,若是沒有出現,則返回-1編程

  • 5. strings.Replace(str string, old string, new string, n int):字符串替換數組

  • 6. strings.Count(str string, substr string)int:字符串計數ide

  • 7. strings.Repeat(str string, count int)string:重複count次str函數

  • 8. strings.ToLower(str string)string:轉爲小寫性能

  • 9. strings.ToUpper(str string)string:轉爲大寫url

  • 10. strings.TrimSpace(str string):去掉字符串首尾空白字符spa

  • 11. strings.Trim(str string, cut string):去掉字符串首尾cut字符

  • 12. strings.TrimLeft(str string, cut string):去掉字符串首cut字符

  • 13. strings.TrimRight(str string, cut string):去掉字符串首cut字符

  • 14. strings.Field(str string):返回str空格分隔的全部子串的slice

  • 15. strings.Split(str string, split string):返回str split分隔的全部子串的slice

  • 16. strings.Join(s1 []string, sep string):用sep把s1中的全部元素連接起來

  • 17. strings.Itoa(i int):把一個整數i轉成字符串

  • 18. strings.Atoi(str string)(int, error):把一個字符串轉成整數

練習1:判斷一個url是否以http://開頭,若是不是,則加上http://,判斷一個路徑是否以「/」結尾,若是不是,則加上/。

package main

import (
    "fmt"
    "strings"
)

func urlProcess(url string) string {
    result := strings.HasPrefix(url, "http://")
    if !result {
        url = fmt.Sprintf("http://%s", url)
    }
    return url
}
func pathProcess(path string) string {
    result := strings.HasSuffix(path, "/")
    if !result {
        path = fmt.Sprintf("%s/", path)
    }
    strings.Replace()
    return path

}

func main() {
    var (
        url  string
        path string
    )

    fmt.Printf("請輸入一個url地址和path路徑:")
    fmt.Scanf("%s%s", &url, &path)

    url = urlProcess(url)
    path = pathProcess(path)

    fmt.Println(url)
    fmt.Println(path)
}

// 請輸入一個url地址和path路徑: www.baidu.com c:/python
練習一

練習2:寫一個函數分別演示Replace、Count、Repeat、ToLower、ToUpper等的用法

package main

import (
    "fmt"
    "strconv"
    "strings"
)

func main() {
    str := "   hello world abc   \n"
    result := strings.Replace(str, "world", "you", 1)
    fmt.Println("replace:", result)

    count := strings.Count(str, "l")
    fmt.Println("count:", count)

    result = strings.Repeat(str, 3)
    fmt.Println("repeat:", result)

    result = strings.ToLower(str)
    fmt.Println("tolower:", result)

    result = strings.ToUpper(str)
    fmt.Println("toupper:", result)

    result = strings.TrimSpace(str)
    fmt.Println("trimspace:", result)

    result = strings.Trim(str, " \n\r")
    fmt.Println("trim", result)

    result = strings.TrimLeft(str, " \n\r")
    fmt.Println("trimleft:", result)

    result = strings.TrimRight(str, " \n\r")
    fmt.Println("trimright:", result)

    split_result := strings.Fields(str)
    for i := 0; i < len(split_result); i++ {
        fmt.Println(split_result[i])
    }

    split_result = strings.Split(str, "l")
    for i := 0; i < len(split_result); i++ {
        fmt.Println(split_result[i])
    }

    str2 := strings.Join(split_result, "l")
    fmt.Println("join:", str2)

    str2 = strconv.Itoa(1000)
    fmt.Println("Itoa:", str2)

    num, err := strconv.Atoi(str2)
    if err != nil {
        fmt.Println("can not convert str to int", err)
    }
    fmt.Println("number is:", num)
}
練習二

2、時間和日期類型

  • 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"))

練習:寫一個程序,獲取當前時間,並格式化成 2017/06/15 08:05:00形式, 統計一段代碼的執行耗時,單位精確到微秒。

package main

import (
	"fmt"
	"time"
)

func test() {
	time.Sleep(time.Millisecond * 100)
}

func main() {
	now := time.Now()
	fmt.Println(now.Format("2006/01/02 15:04:05"))
	start := time.Now().UnixNano() // 1970年到如今的納秒數
	test()
	end := time.Now().UnixNano()

	fmt.Println("cost:%d us\n", (end-start)/1000)
}

3、指針類型

  • 1. 普通類型,變量存的就是值,也叫值類型

  • 2. 獲取變量的地址,用&,好比: var a int, 獲取a的地址:&a

  • 3. 指針類型,變量存的是一個地址,這個地址存的纔是值

  • 4. 獲取指針類型所指向的值,使用:*,好比:var *p int, 使用*p獲取p指向的值

練習:寫一個程序,獲取一個變量的地址,並打印到終端,寫一個函數,傳入一個int類型的指針,並在函數中修改所指向的值。在main函數中調用這個函數,並把修改先後的值打印到終端,觀察結果

package main

import "fmt"

func modify(n *int) {
	fmt.Println(n)
	*n = 10000000
	return
}

func main() {
	var a int = 10  // 整數類型
	fmt.Println(&a) // 取地址
	fmt.Println(a)  // 取變量值

	var p *int // 指針類型
	p = &a
	fmt.Println(p)  // 取地址
	fmt.Println(*p) // 取指針指向的變量值
	*p = 100        // 修改指針地址指向的變量值
	fmt.Println(a)  // 響應的a的變量值也更改

	var b int = 999
	p = &b
	*p = 5

	fmt.Println(a)
	fmt.Println(b)

	modify(&a)
	fmt.Println(a)
}

4、流程控制

1. if / else 分支判斷

方式一:
if condition1 {
}

方式二:
if condition1 {
    
} else {

方式三:
}
if condition1 {
    
} else if condition2 {

} else if condition3 {
} else {
}

方式四:
if condition1 {
    
}
else {

}

 例子

package main
import 「fmt」
func main() {
    bool1 := true
    if bool1 {
        fmt.Printf(「The value is true\n」)
    } else {
        fmt.Printf(「The value is false\n」)
    }
}


練習:寫一個程序,從終端讀取輸入,並轉成整數,若是轉成整數出錯,則輸出 「can not convert to int」,並返回。不然輸出該整數。

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var str string
	fmt.Printf("請輸入一個字符串:")
	fmt.Scanf("%s", &str)

	number, err := strconv.Atoi(str)
	if err != nil {
		fmt.Println("convert failed, err:", err)
		return
	}
	fmt.Println(number)
}

2. switch case語句

語法

switch var {
	case var1:
	case var2:
	case var3:
	default:
	}

 寫法

寫法一
	var i = 0
	switch i {
	case 0:
	case 1:
		  fmt.Println(「1」)
	case 2:
	fmt.Println(「2」)
	default:
		 fmt.Println(「def」)
	}

寫法二
	var i = 0
	switch i {
	case 0:
			fallthrough
	case 1:
		  fmt.Println(「1」)
	case 2:
	fmt.Println(「2」)
	default:
		 fmt.Println(「def」)
	}

寫法三
	var i = 0
	switch i {
	case 0, 1:
		  fmt.Println(「1」)
	case 2:
	fmt.Println(「2」)
	default:
		 fmt.Println(「def」)
	}
寫法四
	var i = 0
	switch {
	condition1:
		  fmt.Println(「i > 0 and i < 10」)
	condition2:
	fmt.Println(「i > 10 and i < 20」)
	default:
		 fmt.Println(「def」)
	}
	
	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(「def」)
	}
寫法五
	switch i := 0 {
	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」)
	}

練習:猜數字,寫一個程序,隨機生成一個0到100的整數n,而後用戶在終端,輸入數字,若是和n相等,則提示用戶猜對了。若是不相等,則提示用戶,大於或小於n。

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	var n int
	n = rand.Intn(100)
	fmt.Println(n)
	for {
		var input int
		fmt.Printf("請輸入一個0-100的整數:")
		fmt.Scanf("%d\n", &input)
		flag := false
		switch {
		case input == n:
			flag = true
			fmt.Println("you are right")
		case input < n:
			fmt.Printf("%d is smaller\n", input)
		case input > n:
			fmt.Printf("%d is bigger\n", input)
		}
		if flag {
			break
		}
	}
}

3. for 語句

寫法1

for 初始化語句; 條件判斷; 變量修改 {
}

for i := 0 ; i < 100; i++ {
fmt.Printf(「i=%d\n」, i)
}

練習:寫一個程序,在終端打印以下圖形
A
AA
AAA
AAAA
AAAAA

package main

import "fmt"

func Print(n int) {
	for i := 1; i <= n; i++ {
		for j := 0; j < i; j++ {
			fmt.Printf("A")
		}
		fmt.Println()
	}
}

func main() {
	Print(6)
}

寫法二

for  條件 {
}
for i > 0 {
      fmt.Println(「i > 0」)
}

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

for {
      fmt.Println(「i > 0」)
}

 寫法三 for range語句

str := 「hello world,中國」
for i, v := range str {
     fmt.Printf(「index[%d] val[%c] len[%d]\n」, i, v, len([]byte(v)))
}

 用來遍歷數組、slice、map、chan

寫法四  break,coutinue語句

str := 「hello world,中國」
for i, v := range str {
       if i > 2 {
             continue
       }
  if (i > 3) {
         break  }
     fmt.Printf(「index[%d] val[%c] len[%d]\n」, i, v, len([]byte(v)))
}

 4. goto和label語句

package main
import "fmt"
func main() {
LABEL1:
	for i := 0; i <= 5; i++ {
		for j := 0; j <= 5; j++ {
			if j == 4 {
				continue LABEL1
			}
			fmt.Printf("i is: %d, and j is: %d\n", i, j)
		}
	}
}


package main

func main() {
	i := 0
HERE:
	print(i)
	i++
	if i == 5 {
		return
	}
	goto HERE
}

5、函數

1. 語法

聲明語法:func 函數名 (參數列表) [(返回值列表)] {}

2. golang 函數特色

  • a. 不支持重載,一個包不能有兩個名字同樣的函數

  • b. 函數是一等公民,函數也是一種類型,一個函數能夠賦值給變量

  • c. 匿名函數

  • d. 多返回值

 例

package main

import "fmt"

func add(a, b int) int {
	return a + b
}

func test() {
	return
}

func main() {
	c := add
	sum := c(200, 300)
	fmt.Println(sum)

	str := "hello world,中國"
	for index, val := range str {
		fmt.Printf("index[%d] val[%c] len[%d]\n", index, val, len([]byte(string(val))))
	}
}

 例2

package main

import "fmt"

type op_func func(int, int) int

func add(a, b int) int {
	return a + b
}

func sub(a, b int) int {
	return a - b
}

func operator(op func(int, int) int, a, b int) int {
	return op(a, b)
}

func main() {
	var c op_func
	c = add
	// c := add

	sum := operator(c, 100, 200)
	dif := operator(sub, 100, 200)

	fmt.Println(sum)
	fmt.Println(dif)
}

3. 函數傳參的兩種方式

  1). 值傳遞

  2) 引用傳遞

注意1:不管是值傳遞,仍是引用傳遞,傳遞給函數的都是變量的副本,不過,值傳遞是值的拷貝。引用傳遞是地址的拷貝,通常來講,地址拷貝更爲高效。而值拷貝取決於拷貝的對象大小,對象越大,則性能越低。
注意2:map、slice、chan、指針、interface默認以引用的方式傳遞

 

package main

import "fmt"

func modify(a int) {
	a = 100
}

func main() {
	a := 8
	fmt.Println(a)
	modify(a)
	fmt.Println(a)
}

4. 命名返回值的名字

func add(a, b int) (c int) {
        c = a + b
        return
}

func calc(a, b int) (sum int, avg int) {
        sum = a + b
        avg = (a +b)/2
        return
}

5. _標識符,用來忽略返回值

func calc(a, b int) (sum int, avg int) {
        sum = a + b
        avg = (a +b)/2
        return}
func main() {
      sum, _ := calc(100, 200)
}

6. 可變參數

注意:其中arg是一個slice,咱們能夠經過arg[index]依次訪問全部參數,經過len(arg)來判斷傳遞參數的個數

練習:寫一個函數add,支持1個或多個int相加,並返回相加結果, 寫一個函數concat,支持1個或多個string相拼接,並返回結果

package main

import "fmt"

func add(a int, arg ...int) int {
	var sum int = a
	for i := 0; i < len(arg); i++ {
		sum += arg[i]
	}
	return sum
}

func concat(a string, arg ...string) (result string) {
	result = a
	for i := 0; i < len(arg); i++ {
		result += arg[i]
	}
	return
}

func main() {
	sum := add(10, 3, 5, 6, 6)
	fmt.Println(sum)

	res := concat("hello", " ", "world")
	fmt.Println(res)
}

7. defer用途

  • 1). 當函數返回時,執行defer語句。所以,能夠用來作資源清理
  • 2). 多個defer語句,按先進後出的方式執行
  • 3). defer語句中的變量,在defer聲明時就決定了。

 關閉文件句柄

func read() {
file := open(filename)
defer file.Close()

//文件操做
}  

鎖資源釋放

func read() {
mc.Lock()
defer mc.Unlock()
//其餘操做
}

數據庫鏈接釋放

func read() {
conn := openDatabase()
defer conn.Close()
//其餘操做
}

defer示例

package main

import "fmt"

var (
    result = func(a1 int, b1 int) int {
        return a1 + b1
    }
)

func test(a, b int) int {
    result := func(a1 int, b1 int) int {
        return a1 + b1
    }(a, b)
    return result
}

func main() {
    fmt.Println(test(100, 200))
    fmt.Println(result(100, 200))

    var i int = 0
    // defer語句編譯的時候會把語句放入棧中,函數結尾的時候一個一個出棧執行
    defer fmt.Println(i)
    defer fmt.Println("second")

    i = 10
    fmt.Println(i)
}
defer示例

 

本節做業

  • 1. 編寫程序,在終端輸出九九乘法表。

  • 2. 一個數若是剛好等於它的因子之和,這個數就稱爲「完數」。例如6=1+2+3.編程找出1000之內的全部完數。

  • 3. 輸入一個字符串,判斷其是否爲迴文。迴文字符串是指從左到右讀和從右到左讀徹底相同的字符串。

  • 4. 輸入一行字符,分別統計出其中英文字母、空格、數字和其它字符的個數。

  • 5. 計算兩個大數相加的和,這兩個大數會超過int64的表示範圍.

參考

package main

import "fmt"

func multi() {
    for i := 1; i < 10; i++ {
        for j := 1; j <= i; j++ {
            fmt.Printf("%d*%d=%d\t", i, j, i*j)
        }
        fmt.Println()
    }
}

func main() {
    multi()
}
做業一
package main

import "fmt"

func perfect(n int) bool {
    var sum int = 0
    for i := 1; i < n; i++ {
        if n%i == 0 {
            sum += i
        }
    }
    return sum == n
}

func process(n int) {
    var flag bool = false
    for i := 1; i < n+1; i++ {
        if perfect(i) {
            flag = true
            fmt.Println(i, "是完數")
        }
    }
    if flag == false {
        fmt.Println(n, "之內沒有完數")
    }
}

func main() {
    var n int
    fmt.Printf("請輸入一個數字:")
    fmt.Scanf("%d", &n)
    process(n)
}
做業二
package main

import "fmt"

func process(str string) bool {
    // rune表明一個字符(中文英文均可以)
    // byte表明一個字節,一箇中文字符表明三個字節
    t := []rune(str)
    length := len(t)
    for i, _ := range t {
        if i == length/2 {
            break
        }
        last := length - i - 1
        if t[i] != t[last] {
            return false
        }
    }
    return true
}

func main() {
    var str string
    fmt.Printf("請輸入一個字符串:")
    fmt.Scanf("%s", &str)
    if process(str) {
        fmt.Println(str, "是迴文: yes")
    } else {
        fmt.Println(str, "是迴文: no")
    }
}
做業三
package main

import (
    "bufio"
    "fmt"
    "os"
)

func process(str string) (word_count int, sapce_counr int, number_count int, other_count int) {
    t := []rune(str)
    for _, v := range t {
        switch {
        case v >= 'a' && v <= 'z':
            fallthrough
        case v >= 'A' && v <= 'Z':
            word_count++
        case v == ' ':
            sapce_counr++
        case v >= '0' && v <= '9':
            number_count++
        default:
            other_count++
        }
    }
    return
}

func main() {
    fmt.Printf("請輸入一個字符串:")
    reader := bufio.NewReader(os.Stdin)
    result, _, err := reader.ReadLine()
    if err != nil {
        fmt.Println("read from console err", err)
        return
    }
    wc, sc, nc, oc := process(string(result))
    fmt.Printf("word_count:%d\nspace_count:%d\nnumber_count:%d\nother_count:%d", wc, sc, nc, oc)

}
做業四
package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

func multi(str1, str2 string) (result string) {
    if len(str1) == 0 && len(str2) == 0 {
        result = "0"
        return
    }

    var index1 = len(str1) - 1
    var index2 = len(str2) - 1
    var left int

    for index1 >= 0 && index2 >= 0 {
        c1 := str1[index1] - '0'
        c2 := str2[index2] - '0'

        sum := int(c1) + int(c2) + left
        if sum >= 10 {
            left = 1
        } else {
            left = 0
        }
        c3 := (sum % 10) + '0'
        result = fmt.Sprintf("%c%s", c3, result)
        index1--
        index2--
    }
    for index1 >= 0 {
        c1 := str1[index1] - '0'
        sum := int(c1) + left
        if sum >= 10 {
            left = 1
        } else {
            left = 0
        }
        c3 := (sum % 10) + '0'
        result = fmt.Sprintf("%c%s", c3, result)
        index1--
    }
    for index2 >= 0 {
        c1 := str2[index2] - '0'
        sum := int(c1) + left
        if sum >= 10 {
            left = 1
        } else {
            left = 0
        }
        c3 := (sum % 10) + '0'
        result = fmt.Sprintf("%c%s", c3, result)
        index2--
    }
    if left == 1 {
        result = fmt.Sprintf("1%s", result)
    }
    return
}

func main() {
    fmt.Printf("請輸入一個字符串:")
    reader := bufio.NewReader(os.Stdin)
    result, _, err := reader.ReadLine()
    if err != nil {
        fmt.Println("read from console err", err)
        return
    }
    strSlice := strings.Split(string(result), "+")
    if len(strSlice) != 2 {
        fmt.Println("please input a+b")
        return
    }
    strNumber1 := strings.TrimSpace(strSlice[0])
    strNumber2 := strings.TrimSpace(strSlice[1])
    fmt.Println(multi(strNumber1, strNumber2))
}
做業五
相關文章
相關標籤/搜索