Go-day03

  概要:

  1.strings与strconv的使用

  2.Go中的时间和日期类型

      3.流程控制

  4.函数详解

strings与strconv用法

1.strings.HasPrefix(s string, prefix string) bool:判断字符串s是否以prefix开头 。
2. strings.HasSuffix(s string, suffix string) bool:判断字符串s是否以suffix结尾。
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:字符串计数
7. strings.Repeat(str string, count int)string:重复count次str
8. strings.ToLower(str string)string:转为小写
9. strings.ToUpper(str string)string:转为大写 9. strings.TrimSpace(str string):去掉字符串首尾空白字符 strings.Trim(str string, cut string):去掉字符串首尾cut字符 strings.TrimLeft(str string, cut string):去掉字符串首cut字符 strings.TrimRight(str string, cut string):去掉字符串首cut字符 10. strings.Field(str string):返回str空格分隔的所有子串的slice strings.Split(str string, split string):返回str split分隔的所有子串的slice 11. strings.Join(s1 []string, sep string):用sep把s1中的所有元素链接起来 12. strconv.Itoa(i int):把一个整数i转成字符串 13. strconv.Atoi(str string)(int, error):把一个字符串转成整数

 练习:  

  练习1:判断一个url是否以http://开头,如果不是,则加上http://。
  练习2:判断一个路径是否以“/”结尾,如果不是,则加上/。

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
	var path string
	fmt.Scanf("%s%s" ,&url,&path)
	result_url := urlProcess(url)
	result_path := pathProcess(path)
	fmt.Println(result_url)
	fmt.Println(result_path)
}

/*
输入: www.baidu.com c:/study
输出: http://www.baidu.com c:/study/ */

练习:

package main

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

func main() {
	str := "hello world world\n"

	result := strings.Index(str,"h") //获取index,首次出现h的位置,获取不到返回-1
	fmt.Println("Index is :",result)

	result = strings.LastIndex(str,"l") //获取str中l最后出现的位置,没有返回-1
	fmt.Println("LastIndex is :",result)

	replaceResult := strings.Replace(str,"world","myself",1) //替换当最后的int为-1时候,替换所有,等于0的时候不替换
	fmt.Println("Replace is :",replaceResult)


	count := strings.Count(str,"l") //求某个字符串出现的次数
	fmt.Println("count is :",count)

	repeatResult := strings.Repeat(str,2) //字符串重复几次
	fmt.Println("repeat_result is :",repeatResult)

	tolowerResult := strings.ToLower(str) //全部变小写
	fmt.Println("tolower_result is :",tolowerResult)

	toupperResult := strings.ToUpper(str) //全部变大写
	fmt.Println("toupper_result is :",toupperResult)

	trimspaceResult := strings.TrimSpace(str) //去掉左右两头空格,默认\n也会去掉
	fmt.Println("trimspace result is :",trimspaceResult)

	trimResult := strings.Trim(str,"\n") //自定义替换方式
	fmt.Println("trims result is :",trimResult)

	trimLeftResult := strings.TrimLeft(str,"\n") //去掉左侧的\n
	fmt.Println("trimLeftspace result is :",trimLeftResult)

	trimRightResult := strings.TrimRight(str,"\n") //去掉右侧的\n
	fmt.Println("trimRightspace result is :",trimRightResult)


	feildResult := strings.Fields(str)  //将字符串以数组形式返回,默认以空格切割
	for i := 0; i < len(feildResult) ; i++ {
		fmt.Println(feildResult[i])
	}

	spiltResult := strings.Split(str,"l") //将字符串以l切割
	for i := 0; i < len(spiltResult) ; i++ {
		fmt.Println(spiltResult[i])
	}

	joinResult := strings.Join(spiltResult,"l") //将数组join到一期
	fmt.Println("join str is ",joinResult)

	myInt := 100
	itoaResult := strconv.Itoa(myInt) //将整数转化为字符串
	fmt.Println("itoa is ",itoaResult)


	atoiResult,err := strconv.Atoi(itoaResult) //将字符串转化为整数
	if err != nil{
		fmt.Println("this is not convert :",err)
	}
	fmt.Println("atoi is :",atoiResult)

}

/*
Index is : 0
LastIndex is : 15
Replace is : hello myself world

count is : 4
repeat_result is : hello world world
hello world world

tolower_result is : hello world world

toupper_result is : HELLO WORLD WORLD

trimspace result is : hello world world
trims result is : hello world world
trimLeftspace result is : hello world world

trimRightspace result is : hello world world
hello
world
world
he

o wor
d wor
d

join str is  hello world world

itoa is  100
atoi is : 100

*/

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

 练习:

  练习1:写一个程序,获取当前时间,并格式化成 2017/06/15 08:05:00形式
  练习2:写一个程序,统计一段代码的执行耗时,单位精确到微秒。

package main

import (
	"time"
	"fmt"
)

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

func main() {
	nowTime := time.Now()
	fmt.Println(nowTime.Format("2006/01/02 15:04:05"))

	startTime := time.Now().UnixNano()
	test()
	endTime := time.Now().UnixNano()
	fmt.Printf("cost time is %d us \n",(endTime - startTime) / 1000)


}

/*
2018/05/05 20:03:11
cost time is 103321 us
*/

指针类型 

练习:

  练习1:写一个程序,获取一个变量的地址,并打印到终端。
  练习2:写一个函数,传入一个int类型的指针,并在函数中修改所指向的值。在main函数中调用这个函数,并把修改前后的值打印到终端,观察结果

 

package main

import "fmt"

func test(p *int ){
	fmt.Println(p)
	*p = 10000
	return
}

func main() {
	var a int = 10
	fmt.Println(&a) //获取内存地址

	var p *int //定义一个指针
	p = &a
	*p = 20
	fmt.Println(*p) //打印指针对应的数值
	fmt.Println(a)

	var b int = 999
	p = &b  //将指针p的内存地址改为了b,修改指针p的值对b无影响
	*p = 5

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

	test(&a) //将内存地址传如函数,函数内修改指针对应的值,影响a
	fmt.Println(a)
	
}


/*
0xc42007e008
20
20
20
5
0xc42007e008
10000
*/

 流程控制

1. if/else

练习:

  写一个程序,从终端读取输入,并转成整数,如果转成整数出错,则输出 “can not convert to int”,并返回。否则输出该整数。

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var a string
	fmt.Scanf("%s",&a)

	number, err := strconv.Atoi(a)
	if err != nil {
		fmt.Println("this is not convert ",err)
	}
	fmt.Println(number)
}

/*
sdad
this is not convert  strconv.Atoi: parsing "sdad": invalid syntax
*/

1. switch case

  switch写法一:

package main

import "fmt"

func main() {
	var a int = 100

	switch a {  //switch 不需要加break,跟shell中的case很像
		case 100:
			fmt.Println("this is 0")
			fallthrough //执行后继续往下走 不判断
		case 10:
			fmt.Println("this is 10")

	    case 0,1,2,3,4,5: //多个条件都走一个分支
			fmt.Println("1,2,3,4,5,0 is ok")
		
		default:
			fmt.Println("this is default")
		
	}
}

   switch写法二:

package main

import "fmt"

func main() {

	var a int = 5
	switch {
		case a >0 && a < 10:
			fmt.Println(" a > 0 & a < 10")

		case a >10 && a < 20:
			fmt.Println("a > 10 & a < 20")

		default:
			fmt.Println("default")
	}

}

   switch写法三:

package main

import "fmt"

func main() {
	
	switch  a :=5; { //直接赋值
 		case a >0 && a < 10:
			fmt.Println(" a > 0 & a < 10")

		case a >10 && a < 20:
			fmt.Println("a > 10 & a < 20")

		default:
			fmt.Println("default")
	}

}

 练习:

  猜数字,写一个程序,随机生成一个0到100的整数n,然后用户在终端,输入数字,如果和n相等,则提示用户猜对了。如果不相等,则提示用户,大于或小于n。

package main

import (
	"fmt"
	"math/rand"
)

func main() {

	num := rand.Intn(100)

	for {
		var input int
		fmt.Scanf("%d\n",&input)
		flag := false
		switch  {
			case num == input:
				fmt.Println("you are right")
				flag = true
			case input < num:
				fmt.Println("less")
			case input > num:
				fmt.Println("bigger")

		}
		if flag{
			break
		}
	}

}

for循环练习:

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)

}

/*
A
AA
AAA
AAAA
AAAAA
AAAAAA
*/

 for与range合用:

  用来遍历数组、slice、map、chan

package main

import "fmt"

func main() {
	var word string = "hello world ,中国"

	for key,value := range word { //range比遍历数组
		fmt.Printf("key[%d],value[%c],len[%d]\n",key,value,len([]byte(string(value))))
		//cannot convert value (type rune) to type []byte  --- value是rune字符型

	}
}

/*
key[0],value[h],len[1]
key[1],value[e],len[1]
key[2],value[l],len[1]
key[3],value[l],len[1]
key[4],value[o],len[1]
key[5],value[ ],len[1]
key[6],value[w],len[1]
key[7],value[o],len[1]
key[8],value[r],len[1]
key[9],value[l],len[1]
key[10],value[d],len[1]
key[11],value[ ],len[1]
key[12],value[,],len[1]
key[13],value[中],len[3] //中文是三个字符
key[16],value[国],len[3]
*/

 for中goto和label使用

例子1: 

package main

import "fmt"

func main() {

	LABLE1:
		for i := 0; i < 5; i++{
			for j :=0 ; j < 5 ;j++{
				if j == 4 { //当j等于4的时候就跳到LABLE1下在执行,不会只跳过j循环
					continue LABLE1
				}
				fmt.Printf("i:[%d],j:[%d]\n",i,j)
			}
		}

}


/*

i:[0],j:[0]
i:[0],j:[1]
i:[0],j:[2]
i:[0],j:[3]
i:[1],j:[0]
i:[1],j:[1]
i:[1],j:[2]
i:[1],j:[3]
i:[2],j:[0]
i:[2],j:[1]
i:[2],j:[2]
i:[2],j:[3]
i:[3],j:[0]
i:[3],j:[1]
i:[3],j:[2]
i:[3],j:[3]
i:[4],j:[0]
i:[4],j:[1]
i:[4],j:[2]
i:[4],j:[3]

*/

 例子2:

package main

import "fmt"

func main() {

	LABLE1:
		for i := 0; i < 5; i++{
			for j :=0 ; j < 5 ;j++{
				if j == 4 { //当j等于4的时候就跳到LABLE1下在执行,不会只跳过j循环
					goto LABLE1
				}
				fmt.Printf("i:[%d],j:[%d]\n",i,j)
			}
		}

}

函数

  go函数特点:  

    a. 不支持重载,一个包不能有两个名字一样的函数
    b. 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量
    c. 匿名函数
    d. 多返回值

package main

import "fmt"

type op_func func(int ,int ) int //通过type定义了一个函数类型

func add (a,b int) int {  //这个传入和返回值必须和定义的一致
	return a + b
}

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

}

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

func main() {
	 //c := add
	 //sum := operator(100,200,c)
	 sum := operator(100,200,sub) //直接传入函数名也可以

	 fmt.Println(sum)
}

   错误例子:

package main
import "fmt"

type add_func func(int, int) int

func add(a, b, c int) int { //这里传了3个值,但是定义类型的时候传入的是2个,所以会编译不过去
	return a + b
}
func operator(op add_func, a int, b int) int {
	return op(a, b)
}

func main() {
	c := addfmt.Println(c)
	sum := operator(c, 100, 200)
	fmt.Println(sum)
}   

  函数参数传递方式:
    1). 值传递
    2). 引用传递

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

    map、slice、chan、指针、interface默认以引用的方式传递

  命名返回值的名字:

func add(a, b int) (c int) {
	c = a + b  //这里不需要做变量定义直接赋值即可
	return 
}
func calc(a, b int) (sum int, avg int) {
	sum = a + bavg = (a +b)/2
	return
}

   _标识符,用来忽略返回值:

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

   可变参数:

  arg ...int告诉Go这个函数接受不定数量的参数。注意,这些参数的类型全部是int。在函数体中,变量arg是一个intslice

for _, n := range arg {
	fmt.Printf("And the number is: %d\n", n)
}

 练习:  

  1.f写一个函数add,支持1个或多个int相加,并返回相加结果
  2.写一个函数concat,支持1个或多个string相拼接,并返回结果

package main

import "fmt"

func add_avg (a int,arg ...int) int{ // arg ...int 可变长参数
	sum := 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_avg(10,100,1000)
	fmt.Println(sum)

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

}   

  defer用途:
    1. 当函数返回时,执行defer语句。因此,可以用来做资源清理
    2. 多个defer语句,按先进后出的方式执行 栈的模式
    3. defer语句中的变量,在defer声明时就决定了。
    4. defer在return或者函数结束后执行,从栈中后进先出的方式出栈

    5.Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题

package main

import "fmt"

//def read(){
//	conn,err := openConn()
//
//	defer func(){   //匿名函数与defer结合
//		if conn != nil {
//			conn.Close()
//		}
//	}()
//
//}

var (
	result = func(a,b int) int{  //定义一个全局的匿名函数,前提要有变量接收这个匿名函数
		return a + b
	}
)

func dtest(a,b int) int{
	result := func(a1,b1 int) int{  //定义一个匿名函数
		return a1 + b1
	}(a,b)

	return result

}

func main() {

	res_1 := result(400,800)
	fmt.Println(res_1)

	res := dtest(100,300)
	fmt.Println(res)

	i := 0
	//首先定义defer不会执行,这个时候i=0,之后无论i怎么修改都不会改变(因为fmt的函数传入的是值类型),
	// 然后将defer压入栈中,在整个程序执行完毕后,从栈中依次执行
	defer fmt.Println(i)
	defer fmt.Println("second")


	i = 10
	fmt.Println(10)

}

   defer用途一:

 

  defer用途二: 

  defer用途三:

  匿名函数:

var (
	result = func(a,b int) int{  //定义一个全局的匿名函数,前提要有变量接收这个匿名函数
		return a + b
	}
)

func dtest(a,b int) int{
	result := func(a1,b1 int) int{  //定义一个匿名函数
		return a1 + b1
	}(a,b)

	return result

}

  函数传递指针的优势:

    • 传指针使得多个函数能操作同一个对象。
    • 传指针比较轻量级 (8bytes),只是传内存地址,我们可以用指针传递体积大的结构体。如果用参数值传递的话, 在每次copy上面就会花费相对较多的系统开销(内存和时间)。所以当你要传递大的结构体的时候,用指针是一个明智的选择。
    • Go语言中channelslicemap这三种类型的实现机制类似指针,所以可以直接传递,而不用取地址后传递指针。(注:若函数需改变slice的长度,则仍需要取地址传递指针)

练习:

  1.99乘法表:

package main

import "fmt"

func muitl(){
	for i :=1; i < 10 ; i++{
		for j :=1; j <= i; j++{ //注意是=号
			fmt.Printf("%d*%d=%d ",i,j,i*j)
		}
		fmt.Println()
	}
}

func main() {
	muitl()
}

/*
1*1=1 
2*1=2 2*2=4 
3*1=3 3*2=6 3*3=9 
4*1=4 4*2=8 4*3=12 4*4=16 
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

*/

   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{ //自己取余为0
			sum += i
		}

	}
	return sum == n
}

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

func main() {
	var input int
	fmt.Scanf("%d",&input)

	process(input)
}

 

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

package main

import "fmt"

func reverse(n string) (result bool){

	t := []rune(n)
	length := len(t)
	for i,_ := range t{
		if i == length/2{ //等于中间的下角标就跳出 例如1221 -->到12就停止
			break
		}

		last := length -i - 1
		if t[i] != t[last]{
			result = false
		}else{
			result = true
		}
	}
	return
}


func main() {
	var input string
	fmt.Scanf("%s",&input)

	res := reverse(input)
	if res{
		fmt.Println("ok")
	}else{
		fmt.Println("no")
	}
}

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

package main

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

func count(str string) (wordCount,spaceCount,intCount,otherCount int){
	
	n := []rune(str) //字符slice
	for _,v := range n{
		switch  {
		case v >= 'a' && v <= 'z':
			fallthrough
		case v >= 'A' && v <= 'Z':
			wordCount++

		case v >= '0' && v <= '9':
			intCount++

		case v == ' ':
			spaceCount++

		default:
			otherCount++
		}
	}
	return
	
}

func main() {
	reader := bufio.NewReader(os.Stdin) //读一行
	result,_,err := reader.ReadLine() //返回一行

	if err != nil{
		fmt.Printf("read from console err:",err)
	}
	wc,sc,ic,oc := count(string(result))

	fmt.Printf("wordCount=%d\nspaceCount=%d\nintCount=%d\notherCount=%d",wc,sc,ic,oc)

}

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

package main

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

//思路 将两个数字变成字符串 跟字符0去做差,然后求和
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'  //返回的是str
		c2 := str2[index2] - '0'  //返回的是str

		sum := int(c1) + int(c2) + left //数字相加进位
		if sum >= 10 {
			left = 1
		} else {
			left = 0
		}
		c3 := (sum % 10) + '0' //取余,在与字符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 { //判断最后的进位是否仍然是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 @ 2018-05-05 17:05  dragonliu  阅读(193)  评论(0)    收藏  举报