Golang教程第3篇:包-strings、strconv、time

1.上周作业

上周有三个练习,写的比较局限,更新了写法
练习1:输出100-200之间的素数及其个数

package main

import (
    "fmt"
)

func IsPrime(a int) bool {
    for i := 2;i < a;i++ {
        if a%i == 0 {
            return false
        }
    }
    return true
}

func main() {
    var n int
    var m int
    var k int
    
    fmt.Scanf("%d %d",&n,&m)
    for j := n;i < m + 1;j++ {
        if IsPrime(j) == true {
            fmt.Printf("%d",j)
            k = k +1
        }
    }
    fmt.Printf("There are %d 素数",k)
}
}

重点说一下这里为什么在Scanf函数中传递变量地址?

从上面的代码中声明了变量n,m,两者默认值为0,fmt包调用Scanf函数请求在终端输入两个数,这里传入了两个变量n与m,注意这里的n与m是前面全局变量n与m的副本,为了区分,我们将其用n1 m1,这个时候如果终端输入数值,假如是100,那么n1就等于100,但是n不等于100,仍然等于0,这就会导致后面是用变量n报错,所以需要传入一个地址&n,分配的内存地址与n一样,输入100时,n的值会变成100

该代码比练习1-输出素数更灵活,可以自由控制范围,但是缺点就是需要手动输入范围数值

练习2:输出100-1000之间的水仙花数,水仙花数是指该数的各个位的立方和等于该数

package main

import (
    "fmt"
    "strconv"
)

func IsShui(a int) bool {
    var str string
    str = strconv.Itoa(a)
    substr1 := str[0:1]
    substr2 := str[1:2]
    substr3 := str[2:]
    
    num1,_ := strconv.Atoi(substr1)
    num2,_ := strconv.Atoi(substr2)
    num3,_ := strconv.Atoi(substr3)
    
    if num1 * num1 * num1 + num2 * num2 * num2 + num3 * num3 * num3 == a {
        return true
    }
    return false
}

func main() {
    var n int
    var m int
    fmt.Scanf("%d %d",&n,&m)
    
    for i := n;i < m + 1;i++ {
        fmt.Printf("%d\n",i)
    }
}

上面在进行计算进行了字符串与整型的类型转换,其实不必这样,获取一个数字的个、十、百位有更简单的方法

package main

import (
    "fmt"
)

func IsShui(a int) bool {
    var i int
    var j int
    var k int
    i = a % 10
    j = (a / 10) % 10
    k = (a / 100) % 10
    
    num := i * i * i + j * j * j + k * k * k
    if num == a {
        return true
    }
    return false
}

func main() {
    var n int
    var m int
    fmt.Scanf("%d%d",&n,&m)
    
    for p := n;p < m;p++ {
        if IsShui(p) == true {
            fmt.Printf("%d\n",p)
        }
    }
}

其实还可以利用go里面所有的字符和整数都是通过ascii码来存储的,如果用每一个数字对应的ascii码减去字符'0'就可以获得该数字的对应值,但是该值默认是byte型,需要int类型转换

package main

import (
    "fmt"
    "strconv"
)

func IsShui(j int) bool {
    var result int = 0
    str := strconv.Itoa(j)
    for i := 0;i < len(str);i++ {
        num := int(str[i] - '0') // ascii码值相减获取该数值
        result = result + num*num*num    
    }
    result1,_ :== strconv.Atoi(str)
    if result == result1 {
        return true
    }
    return false
}

func main() {
    var n string
    var m string
    fmt.Scanf("%s%s",&n,&m)
    
    num1,_ := strconv.Atoi(n)
    num2,_ := strconv.Atoi(m)
    for j := num1;j < num2;j++ {
        if IsShui(j) == true {
            fmt.Printf("%d\n",j)
        }
    }
}

写了一大堆其实还没有前面两种方式简单,之所以这样写主要是想测试一下通过ascii码来获取对应的数值

练习3:取一个数n,计算1!+ 2! + 3! + ... + n!

package main

import (
    "fmt"
)

func JieChen(a int) int {
    var sum int
    var s int = 1
    for i := 1;i <= a;i++{
        s = s * i
        sum += s
    }
    return sum
}

func main() {
    var n int
    fmt.Scanf("%d",&n)
   
    s1 := Jiechen(n)
    fmt.Println(s1)
}

上面的代码只用了一个for循环

经过一段时间学习,自己也有了一点go代码的小心得,下面是我自己重新写的一个例子,原则上是入口函数里只进行输入输出,功能部分均自定义函数实现,尽量让程序更加具有可读性

package main

import (
    "fmt"
)

func Sum(n int) (sum int) {
    for i := 1;i <= n;i++ {
        result := Add(i)
        sum += result
    }
    return
}

func Add(i int) (result int) {
    for a := 1;a <= i;a++ {
        result *= a
    }
    return
}

func main() {
    var n int
    fmt.Scanf("%d",&n)
    
    result := Sum(n)
    fmt.Printf("result=%d\n",result)
}

这样的写法比老师写的复杂,多用了一个循环,但理解起来更清晰

2.strings与strconv

利用函数strings.HasPrefix、strings.HasSuffix、strings.Index、strings.LastIndex来判断字符串

1:使用函数strings.HasPrefix(s string prefix string) bool判断字符串s是否以prefix开头
2:使用函数strings.HasSuffix(s string prefix string) bool判断字符串s是否以prefix结尾
3: 使用函数strings.Index(s string str string) int判断str首次在s出现的位置,如果没有出现则返回-1
str
4: 使用函数strings.LastIndex(s string str string) int判断str在s中最后出现的位置,如果没有则返回-1

先附上我自己写的代码

package main

import (
    "fmt"
    "strings"
)

func IsHTTPHead(str1 string) {
    a := strings.HasPrefix(str "http://")
    if a == true {
        fmt.Println(str1)
    } else {
        str1 = "http://" + str1
        fmt.Println(str1)
    }
}

func IsHTTPTail(str1 string) {
    a := strings.HasSuffix(str1,"/")
    if a == true {
        fmt.Printfln(str1)
    } else {
        str1 = str1 + "/"
        fmt.Println(str1)
    }
}

func IsIndex(str1 string) {
    a := strings.Index(str1,"linuxwt")
    if a == -1 {
        fmt.Println("不存在")
    } else if a == 4 {
        fmt.Println("位置正确")
    } else {
        fmt.Println("位置不正确")
    }
}

func IsLastIndex(str1 string) {
    a := strings.LastIndex(str1,"/")
    if a == -1 {
        fmt.Println("不存在")
    } else if a == 10 {
        fmt.Println("位置正确")
    } else {
        fmt.Println("位置不正确")
    }
}

func main() {
    var (
    str1 string
    str2 string
    str3 string
    str4 string
    )
    
    fmt.Scanf("%s%s%s%s",&str1,&str2,&str3,&str4)
    IsHTTPHead(str1)
    IsHTTPTail(str2)
    IsIndex(str3)
    IsLASTIndex(str4)
}

编译执行
05go14

下面是老师写的

package main
import (
    "fmt"
    "strings"
)

// URLProcess is a function for 判断字符串是否以某个字符(http://)串开头
func URLProcess(url string) string {
    result := strings.HasPrefix(url,"http://")
    if !result {
        url = fmt.Sprintf("http://%s",url)
    }
    return url
}

// PathProcess is a function for 判断字符串是否以某个字符串(/)结尾
func PathProcess(path string) string {
    result := strings.HasSuffix(path,"/")
    if !result {
        path = fmt.Sprintf("%s/",path)
    }
    return path
}

// FirstIndex is a function for 判断子字符串(baidu)在字符串中首次出现的位置
func FirstIndex(first string) string {
    result := strings.Index(first,"baidu")
    if result == 4 {
        first = fmt.Sprintf("判断正确")
    } else if result == -1 {
        first = fmt.Sprintf("不存在")
    } else {
        first = fmt.Sprintf("判断错误")
    }
    return first
}

// EndIndex is a function for 判断子字符串(com)在字符串中最后出现的位置
func EndIndex(end string) string {
    result := strings.LastIndex(end,"com")
    if result == 10 {
        end = fmt.Sprintf("判断正确")
    } else if result == -1 {
        end = fmt.Sprintf("不存在")
    } else {
        end = fmt.Sprintf("判断错误")
    }
    return end
}

func main() {
    var (
        url string
        path string
        first string
        end string
    )
    
    fmt.Scanf("%s%s%s%s",&url,&path,&first,&end)
    
    url = URLProcess(url)
    path = PathProcess(path)
    first = FirstIndex(first)
    end = EndIndex(end)
    
    fmt.Println(url)
    fmt.Println(path)
    fmt.Println(first)
    fmt.Println(end)
}

编译执行输出
05go15

5、字符串替换函数strings.Replace(str string,old string,new string,n int)n为替换的次数
6、字符串计数函数strings.Count(str string,substr string)

7、重复k次str函数strings.Repeat(str string,k int)

8、字符串转换为小写函数strings.ToLower(str string)

9、字符串转换为大写函数strings.ToUpper(str string)

下面附上代码例子

package main

import (
    "strings"
    "fmt"
)

// Replace is a function for 字符串替换输出
func Repalce(replstr string) string {
    result := strings.Replace(replstr,"wa",3)
    return result
}

// Count is a function for 字符串计数输出
func Count(counstr string) int {
    result := strings.Count(counstr,"wa")
    return result
}

// Repeat is a function for 字符串重复输出
func Repeat(repestr string) string {
    result := strings.Repeat(repestr,2)
    return result
}

// Lower is a function for 字符串转换为小写
func Lower(lowestr string) string {
    result := strings.ToLower(lowestr)
    return result
}

// Upper is a function for 字符串转换为大写
func Upper(uppestr string) string {
    result := strings.ToUpper(uppestr)
    return result
}

func main() {
    var (
        replstr string = "wawawawt"
        counstr string = "wawawawt"
        repestr string = "wawawawt"
        lowestr string = "WAWAWAWT"
        uppestr string = "wawawawt"
        k       int 
    )
    
    replstr = Replace(replstr)
    k       = Count(counstr)
    repestr = Repeat(repestr)
    lowestr = Lower(lowestr)
    uppestr = Upper(uppestr)
    
    fmt.Printf("%s\n",replstr)
    fmt.Printf("%d\n",k)
    fmt.Printf("%s\n",repestr)
    fmt.Printf("%s\n",lowestr)
    fmt.Printf("%s\n",uppestr)
}

编译执行输出
05go16

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

11、strings.Trim(str string,cut string)去掉字符串首尾指定的子串

12、strings.TrimLeft(str string,cut string)去掉字符串首指定的子串

14、strings.TrimRight(str string,cut string)去掉字符串尾指定的子串

代码:

package main

import (
    "fmt"
    "strings"
)

// TrimSp is afunction for 去掉字符串首尾空白
func TrimSp(spacstr string) string {
    result := strings.TrimSpace(spacstr)
    return result
}

// Trim is a function for 去掉字符串首尾指定的字符串
func Trim(htstr string) string {
    result := strings.Trim(htstr,"ab")
    return result
}

// Ltrim is a function for 去掉字符串首指定的字符串
func Ltrim(lstr string) string {
    result := strings.TrimLeft(lstr,"ab")
    return result
}

// Rtrim is a function for 去掉字符串尾指定的字符串
func Rtrim(rstr string) string {
    result := strings.TrimRight(rstr,"ab")
    return result
}

func main() {
    var (
        spacstr string = " abc "
        htstr string = "abbadabcabba"
        lstr string = "abbacdab"
        rstr string = "abcdabba"
    )
    
    spacstr = TrimSp(spacstr)
    htstr = Trim(htstr)
    lstr = Ltrim(lstr)
    rstr = Rtrim(rstr)
    
    fmt.Printf("%s\n",spacstr)
    fmt.Printf("%s\n",htstr)
    fmt.Printf("%s\n",lstr)
    fmt.Printf("%s\n",rstr)
}

编译执行
05go17

15、strings.Fields返回字符串空格分隔的子串slice

16、strings.Split返回字符串非空格分隔的子串slice

代码

package main

import (
    "fmt"
    "strings"
)

// Field is a function for 返回字符串空格分隔的子串slice,只能针对以空格分隔子串的字符串
func Field(field string) []string {
    result := strings.Fields(field)
    return result
} 

// Split is a function for 返回字符串非空格(这里是逗号)分隔的子串slice,但slice仍然是以空格分隔
func Split(split string) []string {
    result := strings.Split(split,",")
    return result
}

func main() {
    var (
        field string = "abc def ghi"
        split string = "abc,def,ghi"
        field1 []string
        split1 []string
    )
    
    field1 = Field(field)
    split1 = Split(split)
    
    fmt.Printf("%s\n",field1)
    fmt.Printf("%s\n",split1)
}

编译执行
05go18

17、strings.Join(s []string,sep string)用sep把s中的元素连接起来

package main

import (
    "fmt"
    "strings"
)

// Slice1 is a function for 使用空格将[]string中的元素连接起来
func Slice1(slice []string) string {
    result ;= strings.Join(slice," ")
    return result
}

// Slice2 is a function for 使用逗号将[]string中的元素连接起来
func Slice2(slice []string) string {
    result := strings.Join(slice,",")
    return result
}

func main() {
    var (
        slice []string = []string{"abc","def","ghi"}
        str1 string
        str2 string
    )
    
    str1 = Slice1(slice)
    str2 = Slice2(slice)
    fmt.Printf("%s\n",str1)
    fmt.Printf("%s\n",str2)
    fmt.Printf("%q\n",str1)
    fmt.Printf("%q\n",str2)
}

编译执行
05go19

18、strconv.Itoa(n int)整数转换成字符串

19、strconv.Atoi(str string) (int,error)字符串转换成整数

代码

package main

import (
    "fmt"
    "strconv"
)

// Exchange1 is a function for 整数转换成字符串
func Exchange1(n int) string {
    result := strconv.Itoa(n)
    return result
}

// Exchange2 is a function for 字符串转换成整数
func Exchange2(str string) int {
    result,err := strconv.Atoa(str)
    if err != nil {
        fmt.Printf("can not convert %s to int.",str)
    }
    return result
}

func main() {
    var (
        n int
        str string
        n1 string
        str1 int
    )
    fmt.Scanf("%d%s",&n,&str)
    
    n1 = Exchange1(n)
    str1 = Exchange2(str)
    
    fmt.Printf("%T %d\n",n,n)
    fmt.Printf("%T %s\n",str,str)
    fmt.Printf("%T %d\n",n1,n1)
    fmt.Printf("%T %s\n",str1,str1)
}

编译执行
05go20

前面学习了strings、strconv包的常规使用,例子都是我自己写的,都采用自定义调用函数的写法作了基本的学习,下面是老师给的例子,主要是方便学习相关知识,抄录下来与自己写的作比较

package main

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

func main() {
    str := "  hello world abc  \n\r"  // \n为换行\r为回车
    
    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:"," \n\r")
    
    fieldresult := strings.Fields(str)
    fmt.Println("Fields:",fieldresult)
    for i := 0;i < len(fieldresult);i++ {
        fmt.Println(fieldresult[i])
    }
    
    splitresult := strings.Split(str)
    fmt.Println("Split:",splitresult)
    for i := 0;i < len(splitresult);i++ {
        fmt.Println(splitresult[i])
    }
    
    result = strings.Join(fieldresult," ")
    fmt.Println("Join:",result)
    
    result = strings.Join(splitresult,"l")
    fmt.Println("Join:",result)
    
    result = strconv.Itoa(1000)
    fmt.Println("Itoa:",result)
    
    number,err := strconv.Atoi(result)
    if err != nil {
        fmt.Printf("can not convert %s to int.",result)
        return
    }
    fmt,Println("Atoi:",number)
}

代码中的str变量是一个值类型,不会因为后面的操作而改变它的值,result这个变量第一次使用是在实现strings.Repalce函数功能时候,该函数返回值为字符串,所以后面在实现strings.Count与strconv.Atoi函数功能的时候不能使用result,因为这两者返回值类型为整型

3.time

获取当前时间并格式化输出

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    
    fmt.Println(now.Format("2006/01/02 15:04:05"))
    fmt.Printf("%s\n",now.Format("2006/01/02 15:04:05"))
    fmt.Printf("%02d/%02d/%02d %02d:%02d:%02d",now.Year(),now.Month(),now.Day(),now.Hour(),now.Minute(),now.Second())
}

编译执行
05go21

time包里面还有一些常规的写法来表示时间单位

  • time.Duration 纳秒
  • time.Microsecond 微秒
  • time.Millisecond 毫秒
  • time.Second 秒
  • time.Minute 分
  • time.Hour

下面是一个简单统计某个程序运行时耗的例子

package main

import (
    "fmt"
    "time"
)

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

func main() {
    now := time.Now()
    start := now.UnixNano()
    Test()
    end := now.UnixNano()
    
    fmt.Printf("cost: %d us",(end - start)/1000)
}

4.包链接

strings
strconv
time