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
相关文章
相关标签/搜索