Go流程控制與函數詳解

1、strings和strconv的使用golang

strings算法

1.func HasPrefix(s, prefix string) bool   判斷字符串s是否以prefix開頭數據庫

func main(){
    a := "hello world"
    if (strings.HasPrefix(a,"hello")){
        fmt.Println("yes")
    }else{
        fmt.Println("no")
    }
}
View Code

2.func HasSuffix(s, suffix string) bool  判斷字符串s是否以prefix結尾安全

3.func Index(s, sep string) int  判斷chars在s首次出現的位置,若是沒有返回-1ide

4.func LastIndex(s, sep string) int   判斷chars在s最後出現的位置,若是沒有返回-1函數

5.func Replace(s, old, new string, n int) string  參數:原字符串,須要替換的,替換成,次數性能

func main(){
    a := "hehehelololo"
    a = strings.Replace(a,"he","wo",2)
    fmt.Println(a)
}
View Code

6.func Count(s, sep string) int  計數,sep在s中出現的次數ui

7.func Repeat(s string, count int) string  重複count次數spa

func main(){
    a := strings.Repeat("he",3)
    fmt.Println(a)
}
View Code

8.func TrimSpace(s string) string  去掉字符串首尾空白字符指針

9.func Trim(s string, cutset string) string  去除字符串首尾cutset字符

10.func TrimLeft(s string, cutset string) string  去掉字符串首cutset字符

11.func TrimRight(s string, cutset string) string  去掉字符串尾cutset字符

12.func Fields(s string) []string   以空格分隔,返回全部子字符串

f := func(c rune) bool {
    return !unicode.IsLetter(c) && !unicode.IsNumber(c)
}
fmt.Printf("Fields are: %q", strings.FieldsFunc("  foo1;bar2,baz3...", f))

# Fields are: ["foo1" "bar2" "baz3"]
View Code

13.func Join(a []string, sep string) string   sep把字符串中的全部元素拼接

strconv

1.strconv.Itoa(i int)  把一個整數i轉換成字符串

2.strconv.Atoi(str string)(int error)  把一個字符串轉換成整數

詳細見文檔:http://docscn.studygolang.com/pkg/

2、時間和日期類型

time包

time.Time類型,用來表示時間
獲取當前時間:now := time.Now()

time.Now().Day(),time.Now().Minute(),time.Now().Month(),time.Now().Year()

格式化

fmt.Printf("%02d/%02d/%02d %02d:%02d:%02d",now.Year()....)
fmt.Printf(now.Format("02/1/2006 15:04:05"))
fmt.Printf(now.Format("2006/1/02 15:04:05"))
fmt.Printf(now.Format("2006/1/02"))


# 時間必須是2006/1/02 15:04:05
func main(){
    now := time.Now()
    fmt.Printf(now.Format("02/1/2006 15:04:05"))
}
eg

一些常量

const(
    Nanosecond Duration = 1
    Microsecond = 1000*Nanosecond
    Millisecond = 1000*Microsecond
    Second = 1000*Millisecond
    Mintue = 60...
    Hour = 60...
)
        
View Code
func test(){
    time.Sleep(99*time.Millisecond)
}

func main(){
    start := time.Now().UnixNano()
    test()
    end := time.Now().UnixNano()
    fmt.Println((end - start)/1000000)
}
計算一個程序的運行時間(微秒級)

 3、值類型與指針類型

1.普通類型,變量存的就是值,也叫值類型
2.獲取變量的地址,用&,好比:var a int,獲取a的地址:&a
3.指針類型,變量存的是一個地址,這個地址存的纔是值h
4.獲取指針類型所指向的值,使用:*,好比:var *p int,使用*p獲取p指向的值

func main(){
    a := 1
    fmt.Println("a的地址:",&a)
}
獲取變量的地址
var n = 1

func modify1(n *int){
    *n = 100
}

func modify2(n int){
    n = 200
}


func main(){
    modify1(&n)
    modify2(n)
    fmt.Println(n)
}

# n=100
值的副本與地址的副本

4、流程控制

1.if/else分支判斷

#形式一
if condition{

}

#形式二
if condition{

}else{

}

#形式三
if condition1{

}else if condition2{

}else if condition3{

}else{

}

#注意:else與else if必須跟在花括號後面
if condition{

}
else{

}  //錯誤
語法

2.switch case語句

switch var{
    case var1:
        // fallthrough穿透(會繼續執行,和其它語言沒有加break效果同樣,go不須要加break)
    case var2:
    case var3:
    default:
}

#寫法1:
switch var{
        //能夠多個值
    case var1,var2:
    case var3, var4:
    case var5:
    default:
}

#寫法2:
var i = 0
switch{       
    condition1:
    condition2
    default:
    }

#寫法3:
switch i :=0{
        //能夠初始化
    case var1,var2:
    case var3, var4:
    case var5:
    default:
}    
語法
#隨機生成0-100的整數,終端用戶輸入猜想的數字,提示大小...
func main(){
    rand.Seed(time.Now().Unix())
    a := rand.Intn(100)
    var n int
    for{
        fmt.Scanf("%d\n",&n)
        switch {
        case a < n:
            fmt.Println("大了")
        case a > n:
            fmt.Println("小了")
        default:
            fmt.Println("ok")
            return
        }
    }
        
}
猜大小

 延展

Go的math/rand包提供了生成隨機數的API,重要的API以下:

// 該函數設置隨機種子
// 若不調用此函數設置隨機種子,則默認的種子值爲1,因爲隨機算法是固定的,
// 若是每次都以1做爲隨機種子開始產生隨機數,則結果都是同樣的,所以通常
// 都須要調用此函數來設置隨機種子,一般的作法是以當前時間做爲隨機種子
// 以保證每次隨機種子都不一樣,從而產生的隨機數也不通
// 該函數協程安全
func Seed(seed int64)

// 如下函數用來生成相應數據類型的隨機數,帶n的版本則生成[0,n)的隨機數。
// 注意生成的隨機數都是非負數
func Float32() float32
func Float64() float64
func Int() int
func Int31() int32  // 注意該函數只返回int32表示範圍內的非負數,位數爲31,所以該函數叫作Int31
func Int31n(n int32) int32
func Int63() int64
func Int63n(n int64) int64
func Intn(n int) int
func Uint32() uint32
func Uint64() uint64

// 另外,rand包還提供了一個類,接口和上面的大體相同:
type Rand struct {
    // ...
}

// 建立一個以seed爲種子的源,注意該源不是協程安全的
func NewSource(seed int64) Source
// 以src爲源建立隨機對象
func New(src Source) *Rand
// 設置或重置種子,注意該函數不是協程安全的
func (r *Rand) Seed(seed int64)
// 下面的函數和全局版本的函數功能同樣
func (r *Rand) Float32() float32
func (r *Rand) Float64() float64
func (r *Rand) Int() int
func (r *Rand) Int31() int32
func (r *Rand) Int31n(n int32) int32
func (r *Rand) Int63() int64
func (r *Rand) Int63n(n int64) int64
func (r *Rand) Intn(n int) int
func (r *Rand) Uint32() uint32
func (r *Rand) Uint64() uint64
API
package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {

    //
    // 全局函數
    //

    rand.Seed(time.Now().Unix())

    fmt.Println(rand.Int())       // int隨機值,返回值爲int
    fmt.Println(rand.Intn(100))   // [0,100)的隨機值,返回值爲int
    fmt.Println(rand.Int31())     // 31位int隨機值,返回值爲int32
    fmt.Println(rand.Int31n(100)) // [0,100)的隨機值,返回值爲int32
    fmt.Println(rand.Float32())   // 32位float隨機值,返回值爲float32
    fmt.Println(rand.Float64())   // 64位float隨機值,返回值爲float64

    // 若是要產生負數到正數的隨機值,只須要將生成的隨機數減去相應數值便可
    fmt.Println(rand.Intn(100) - 50) // [-50, 50)的隨機值

    //
    // Rand對象
    //

    r := rand.New(rand.NewSource(time.Now().Unix()))

    fmt.Println(r.Int())       // int隨機值,返回值爲int
    fmt.Println(r.Intn(100))   // [0,100)的隨機值,返回值爲int
    fmt.Println(r.Int31())     // 31位int隨機值,返回值爲int32
    fmt.Println(r.Int31n(100)) // [0,100)的隨機值,返回值爲int32
    fmt.Println(r.Float32())   // 32位float隨機值,返回值爲float32
    fmt.Println(r.Float64())   // 64位float隨機值,返回值爲float64

    // 若是要產生負數到正數的隨機值,只須要將生成的隨機數減去相應數值便可
    fmt.Println(r.Intn(100) - 50) // [-50, 50)的隨機值
}
例子

3.for循環

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

for與條件

for 條件{

}
func main(){
    a := 5
    for a<=10{
        fmt.Println(a)
        a++
    }
}
例子

for range語句

for i, v :=range str{

}
func main(){
    str := "hello world"
    for i, v :=range str{
        fmt.Printf("index:%v,value:%c\n",i,v)
    }
}
例子

for與continue及break

func main(){
    a := 10
    for i :=1 ;i < a; i++{
        if (a%i==0){
            continue
        }else if(i==9){
            break
        }
        fmt.Println(i)
    }
}
例子

for與LABEL語句

// continue
func main(){
    for i :=1; i <=2; i++{
        for j := 0; j <= 3; j++{
            if (j == 2){
                continue
            }
            fmt.Println(j)
        }
    }
}    
    
#0 1 3 0 1 3

// LABEL
func main(){
    LABEL:
        for i :=1; i <=2; i++{
            for j := 0; j <= 3; j++{
                if (j == 2){
                    continue LABEL
                }
                fmt.Println(j)
            }
        }
}
#0 1 0 1
例子

goto語句

//實現循環功能
func main(){
    i := 0 
    HERE  :
        i++
        if i == 5{
            return
        }
        fmt.Println(i)
        goto HERE
}
例子

5、函數

1.語法

func 函數名 (參數列表) [(返回值列表)]{}
//正確的寫法
func add(a, b int){

}  

func add(a int)
{

}// 錯誤,花括號要和聲明在同一行

2.golang函數特色

不支持重載,一個包不能有兩個名字同樣的函數
函數是一等公民,函數也是一種類型,一個函數能夠賦值給變量
匿名函數
多返回值

package main

import "fmt"

// 函數也是一種類型
type add_func func(int, int) int

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

func operator(op add_func, a int, b int)int{
    return op(a, b)
}
func main(){
        //能夠賦值給變量
        c := add
    sum := operator(c,100,200)
    fmt.Println(sum)
}
例子

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

4.命名返回值的名字

func add(a, b int)(c int){
    c = a + b
    return
    // 就不須要寫成
    // c := a + b
    // return c
}

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

func add(a int, b int)(int, int){
    sum := a + b
    sub := a - b
    return sum, sub
}

func main(){
        //使用_來標識不須要的返回值
    sum, _:=add(200,100)
    fmt.Println(sum)
}

6.可變參數

func add(arg...int)int{}  //三個點修飾表示參數可變, 0個或多個參數
func add(a int, arg...int)int{}  //一個或多個參數

//注意其中arg是一個slice,咱們能夠經過arg[index]依次訪問全部參數,經過len(arg)判斷傳遞參數的個數
func t1(n int,arg...int)(sum int){
    sum = n
    for i :=0; i < len(arg); i++{
        sum += arg[i]
    }
    return
}

func main(){
    s1 := t1(10)
    s2 := t1(10,20,30)
    fmt.Println(s1)
    fmt.Println(s2)
}
例子

7.defer用途

特性:
當函數返回時,執行defer語句,所以,能夠用來作資源清理
多個defer語句,按先進後出的方式執行
defer語句中的變量,在Defer聲明時就決定了

func main(){
    var i int = 0 
    defer  fmt.Println(i)
    defer  fmt.Println("2")
    i = 10
    fmt.Println(i)
}

// 10 2 0
// 能夠反映三個特性
例子

用途:

1.關閉文件句柄

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

2.鎖資源釋放

func read(){
    mc.Lock()
    defer mc.Unlock()
}

3數據庫鏈接釋放

func read(){
    conn :=openDatabase()
    defer conn.Close()
}

6、小練習

1.九九乘法表

package main

import "fmt"

func main(){
    for i := 1; i <= 9; i++{
        for j := 1; j<=i; j++{
            val := j*i
            fmt.Printf("%d*%d=%d ",j,i,val)
        }
    }
}
View Code

2.一個數若是剛好等於它的因子之和,這個數就被稱爲完數,如:6=1+2+3,找出1000內的全部完數

package main

import "fmt"

func check(n int)bool{
    var sum int
    for i := 1; i <= n/2; i++{
        fmt.Println(i)
        if (n % i == 0){
            sum += i
        }
    }
    return sum == n
}

func main(){
    var n int
    if (n == 0){
        fmt.Println("no")
    }
    if (check(n)){
        fmt.Println("yes")
    }else{
        fmt.Println("no")
    }
}
View Code

3.判斷一個輸入的字符串是否爲迴文(從左到右,從右到左同樣)

package main

import "fmt"


func reserve(n string)(m string){
    for i := 0; i < len(n); i++{
        j := len(n) - i -1
        m += string(n[j])
    }
    return 
}

func main(){
    var n string
    fmt.Scanf("%s\n",&n)
    m := reserve(n)
    fmt.Println(n,m)
    if (m==n){
        fmt.Println("true")
    }else{
        fmt.Println("false")
    }
}

// 這種寫法的問題是對於中文沒法處理(中文3個byte)
View Code
//判斷字符串迴文


package main

import "fmt"

func check(n string)bool{
    l := []rune(n)
    length := len(l)
    for i, _ := range l{
        if (i == length/2){
            break
        }
        if (l[i] != l[len(l) - i - 1]){
            return false
        }
    }
    return true
}


func main(){
    var n string
    fmt.Scanf("%s",&n)
    if (check(n)){
        fmt.Println("yes")
    }else{
        fmt.Println("no")
    }
}
改進版

4.輸入字符串,統計英文字母,空格,數字和其它字符的個數
5.計算兩個大數相加的和,這個和可能會超過int64的表示範圍

// 計算兩個大數相加的和,這個和可能會超過int64的表示範圍

package main

import (
    "fmt"
    "math"
    "strconv"
    "strings"
    // "reflect"
)

func addLongNmber(n string, m string) (result string) {
    sign := 0
    for i := len(n) - 1; i >= 0; i-- {
        sum := (n[i] - '0') + (m[i] - '0')

        if sign == 1 {
            sum++
            sign--
        }

        if sum >= 10 {
            sum -= 10
            sign++
        }

        result = strconv.Itoa(int(sum)) + result

    }
    if sign == 1 {
        result = "1" + result
    }

    return
}

func main() {
    var n, m string
    var part string = "0"

    fmt.Scanf("%s %s", &n, &m)

    repeatNum := int(math.Abs(float64(len(n) - len(m))))
    part = strings.Repeat(part, repeatNum)

    if len(n) > len(m) {
        m = part + m
    } else {
        n = part + n
    }

    result := addLongNmber(n, m)
    fmt.Println(result)
}
View Code
相關文章
相關標籤/搜索