返回顶部

03 | 字符串,时间,流程控制,函数

一、strings和strconv的使用

strings

判断字符串s是否以prefix开头

strings.HasPrefix(s string,preffix string) bool:

判断字符串s是否以suffix结尾

stirngs.HasSuffix(s string,suffix string) bool:

判断str在s中首次出现的位置,如果没有出现,则返回-1

strings.Index(s string,str string) int:

判断str在s中最后出现的位置,如果没有出现,则返回-1

strings.LastIndex(s string,str string) int:

字符串替换

strings.Replace(str string,old string,new string,n int):

字符串计数

strings.Count(str string,count int)string:

重复count次str

strings.Repeat(str string,count int) string:

转换为小写

strings.ToLower(str string)

转换为大写

strings.ToUpper(str string)string:

去掉字符串首位空白字符

strings.TrimSpace(str string):

去掉字符串首尾cut字符

strings.Trim(str string,cut string):

去掉字符串首部cut字符

strings.TrimLeft(str string,cut string):

去掉字符串尾部cut字符

strings.TrimRight(str string,cunt string):

返回str空格分隔的所有子串的slice

strings.Field(str string):

返回str split分割的所有子串的slice

string.Split(str string,split string):

用sep把s1中的所有元素连接起来

strings.Join(s1 []string,sep string):  

 

小练习 1 

判断url 不是http://开头 机上http://s  判断是否以 / 结尾,不是加上

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)
    }

    return path
}

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

    fmt.Scanf("%s%s", &url, &path)
    url = urlProcess(url)
    path = pathProcess(path)

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

输出结果如下

 小练习 2

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("lower:", result)

    result = strings.ToUpper(str)
    fmt.Println("upper:", 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)

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

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

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

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

    number, err := strconv.Atoi("abc")
    if err != nil {
        fmt.Println("can not convert to int,", err)
        return
    }

    fmt.Println("number:", number)
}
View Code

strconv

把一个整数转换成字符串

scronv.Itoa(i int):

把一个字符串转换成整数

scronv.Atio(str string)(int,errror):

二、Go中时间和日期

获取当前时间:now:= time.Now()

time.Now().Day() 返回时间点t对应那一月的第几日

time.Now().Minute() 返回t对应的那一小时的第几分种,范围[0, 59]。

time.Now().Month() String返回月份

time.Now().Year()  返回时间点t对应的年份。

time.Duration 用来表示纳秒

一些常用的时间常量

const (
Nanosecond Duration = 1
Microsecond =1000 * Nanosecond
Millisecond =1000 * Microsecond
Second =1000 * Millisecond
Minute =60 * Second
Hour =60 * Minute
)

小案例

写一个程序,获取当前时间,并格式化成 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()
	test()
	end := time.Now().UnixNano()

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

}

输出结果如下

三 指针类型

普通的类型,变量存的就是值,也叫值类型

获取变量的地址,用& 比如: var a int, 获取a的地址:&a

指针类型,变量存的是一个地址,这个地址存的才是真正的值

获取指针类型所指向的值,用*,例如:var *p int, 使用 *p获取p指向值

小案例 1

package main

import "fmt"

func main() {
    var a int = 10
    fmt.Println(&a)

    var p *int
    p = &a
    fmt.Println(*p)
    *p = 100
    fmt.Println(a)
}

输出结果如下

 

小案例 2

package main

import "fmt"

func modify(p *int) {

	fmt.Println(p)
	*p = 1000900
	return
}

func main() {

	var a int = 10
	fmt.Println(&a)

	var p *int
	p = &a

	fmt.Println("the address of p:", &p)
	fmt.Println("the value of p:", p)
	fmt.Println("the value of p point to variable:", *p)

	fmt.Println(*p)
	*p = 100
	fmt.Println(a)

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

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

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

输出结果如下

四、流程控制

if else 分支判断

常见格式类型如下:
if 条件{
}

if 条件{
}else{
}

if 条件{
}else if 条件{
}else{
}

switch case

语法格式:

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

}

如果满足了var1 想要穿透下一个需要添加fallthrough

例子如下:

package main

import "fmt"

func main() {
    var a int = 0

    switch a {
    case 0:
        fmt.Println("a 等于0")
        fallthrough
    case 1:
        fmt.Println("a等于1")
    default:
        fmt.Println("a等于默认值")
    }

}

如果我们没有添加fallthrough只会打印a等于0,但是现在回把case1中的打印内容也打印出来

同样这里我们需要知道case 后面是可以写条件的

输出结果如下

for语句

语法
for 初始化变量;条件判断;变量修改{
}

例子 1

for i:=0;i<100;i++{
    fmt.Println(i)
}

例子 2

package main

import "fmt"

func Print(n int) {

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

func main() {
	Print(6)
}

输出结果如下

 

for循环的其他几种常见写法

for 条件 {
}

死循环的写法
for {
}

for range语句

通过一个例子理解:

package main

import "fmt"

func main() {
	str := "hello 世界"
	for index, val := range str {
		fmt.Printf("index[%d] val[%c] len[%d]\n", index, val, len([]byte(string(val))))
	}
}

这里需要注意的一个问题是,range str返回的是两个值,一个是字符串的下标,一个是字符串中单个的字符

输出结果如下

 

goto 和label语句

package main

import "fmt"

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

代码中我们在continue 后面添加了一个LABEL1这样当循环匹配到j等于4的时候,就会跳出循环,重新回到最外成i的循环,而如果没有LABEL1则就会跳出j的本次循环,执行j++进入到j的下次循环

输出结果如下

我们接着看goto的用法,但是代码中我们不建议使用goto

package main

import "fmt"

func main() {
    i :=0
    HEAR:
    fmt.Println(i)
    i++
    if i == 5{
        return
    }
    goto HEAR
}

输出结果如下

break 和continue
一句话解释:break是终止整个循环,continue是终止此次循环

五、函数详解

声明语法

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){

}

go函数的特点

  1. 不支持重载,一个包不能包含两个名字一样的函数
  2. 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量
  3. 匿名函数
  4. 多返回值

其他几个概念可能都好理解,我们这里主要说说第二条,函数也是一种类型,一个函数可以赋值给变量

通过下面的例子演示

 

package main

import "fmt"

type add_func func(int,int) int


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

func operator(op add_func,a int,b int) int {
    return op(a,b)
}
func main() {
    c := add
    fmt.Println(c)
    sum := operator(c,100,200)
    fmt.Println(sum)
}

这里通过type自定义了一个add_func类型

输出结果如下

 

函数参数传递方式

这里主要有两种方式:值传递,引用传递

无论是值传递还是引用传递,传递给函数的都是变量的副本,不过值传递的是值的拷贝,引用传递传递的是地址的拷贝,一般来说,地址拷贝更为高效,而值拷贝取决于拷贝的对象的大小,对象越大,则性能越低

命名返回值的名字

通过下面的例子理解:

package main
func add_sum(a,b int)(c int){
	c = a + b
	return
}

func main() {
	println(add_sum(10,20))
}

 

在这里返回值c因为在返回值的列表中已经声明了,所以在函数中不用声明,直接return,默认返回的是c

输出结果如下

 

下划线标识符,用来忽略返回值

func main() {
      sum, _ := calc(100, 200)
}

可变参数

表示0个或多个参数
fucn add(arg...int) int{
}

package main

import "fmt"

//接受0个或多个参数
func add(arg...int) int {
	var sum int =0
	for i := 0; i < len(arg); i++ {
		sum += arg[i]
	}

	return sum
}


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

}

输出结果如下

 

表示1个或多个参数
func add(a int,arg...int) int {
}

其中arg是一个slice,我们可以通过arg[index]获取指定位置的参数
通过len(arg)可以判断参数的个数

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, 3, 3, 3)
	fmt.Println(sum)

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

输出结果如下

 

defer用途

  1. 当函数返回时,执行defer语句,可以用来做资源清理

  2. 多个defer语句,按先进后出的方式执行

  3. defer语句中变量,在defer声明时就决定了

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()
//其他操作
}

 

通过下面的例子理解:

package main
import "fmt"

func main() {
    a:=0
    defer fmt.Println("defer---->",a)
    a++
    fmt.Println(a)

}

结果会在最后打印defer---->0 ,这里就体现了defer语句中变量,在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
    }

    return result(a, b)
}

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

    var i int = 0
    defer fmt.Println(i)
    defer fmt.Println("second")

    i = 10
    fmt.Println(i)
}

 

输出结果如下

 小案例

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

package main

import "fmt"

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

func main() {
	multi()
}

输出结果如下

 

2. 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3.

编程找出1000以内的所有完数。

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 n == sum
}

func process(n int) {
	for i := 1; i < n+1; i++ {
		if perfect(i) {
			fmt.Println(i)
		}
	}
}

func main() {
	var n int
	fmt.Scanf("%d", &n)
	process(n)
}

  

输出结果如下

 

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

左读完全相同的字符串。

package main

import "fmt"

func process(str string) bool {

	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.Scanf("%sd", &str)
	if process(str) {
		fmt.Println("yes")
	} else {
		fmt.Println("no")
	}
}

 输出结果如下

 

 

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

package main

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

func count(str string) (worldCount, spaceCount, numberCount, otherCount int) {

	t := []rune(str)
	for _, v := range t {
		switch {
		case v >= 'a' && v <= 'z':
			fallthrough # 如果是小写字母,执行下一行
		case v >= 'A' && v <= 'Z':
			worldCount++
		case v == ' ':
			spaceCount++
		case v >= '0' && v <= '9':
			numberCount++
		default:
			otherCount++
		}
	}

	return
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	result, _, err := reader.ReadLine()
	if err != nil {
		fmt.Println("read from console err:", err)
		return
	}
	wc, sc, nc, oc := count(string(result))
	fmt.Printf("wolrd count:%d\n space count:%d\n number count:%d\n others count:%d\n", wc, sc, nc, oc)
}

 

 输出结果如下

 

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

 

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() {
    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))
}

 

 

 输出结果如下

 

  

 

  

 

posted @ 2019-01-06 00:17  Crazymagic  阅读(210)  评论(0编辑  收藏  举报