GO开发[三]:fmt,strings,strconv,指针,控制结构
一、fmt包
%v 值的默认格式表示。当输出结构体时,扩展标志(%+v)会添加字段名
%#v 值的Go语法表示
%T 值的类型的Go语法表示
%% 百分号
%t 单词true或false
%b 表示为二进制
%c 该值对应的unicode码值
%d 表示为十进制
%o 表示为八进制
%q 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示
%x 表示为十六进制,使用a-f
%X 表示为十六进制,使用A-F
%U 表示为Unicode格式:U+1234,等价于"U+%04X"
%b 无小数部分、二进制指数的科学计数法,如-123456p-78;参见strconv.FormatFloat %e 科学计数法,如-1234.456e+78 %E 科学计数法,如-1234.456E+78 %f 有小数部分但无指数部分,如123.456 %F 等价于%f %g 根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G 根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)
%s 直接输出字符串或者[]byte %q 该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示
%x 每个字节用两字符十六进制数表示(使用a-f)
%X 每个字节用两字符十六进制数表示(使用A-F)
%p 表示为十六进制,并加上前导的0x
宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可能有的)宽度后跟点号后跟的十进制数指定。如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为0。
%f: 默认宽度,默认精度
%9f 宽度9,默认精度
%.2f 默认宽度,精度2 %9.2f 宽度9,精度2 %9.f 宽度9,精度0
+ 总是输出数值的正负号;对%q(%+q)会生成全部是ASCII字符的输出(通过转义);
- 在输出右边填充空白而不是默认的左边(即从默认的右对齐切换为左对齐);
# 切换格式:
八进制数前加0(%#o),十六进制数前加0x(%#x)或0X(%#X),指针去掉前面的0x(%#p);
对%q(%#q),如果strconv.CanBackquote返回真会输出反引号括起来的未转义字符串;
对%U(%#U),如果字符是可打印的,会在输出Unicode格式、空格、单引号括起来的go字面值;
' ' 对数值,正数前加空格而负数前加负号;
对字符串采用%x或%X时(% x或% X)会给各打印的字节之间加空格;
0 使用0而不是空格填充,对于数值类型会把填充的0放在正负号后面;
测试:
package main
import "fmt"
func main() {
a:=fmt.Sprintf("%[2]d %[1]d", 11, 22)
fmt.Println(a)
b:=fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6)
fmt.Println(b) //在'*'之前的[n]符号表示采用第n个参数的值作为宽度或精度
c:=fmt.Sprintf("%4.2f", 12.0)
fmt.Println(c) //显式的索引会影响随后的verb,这种符号可以通过重设索引用于多次打印同一个值
d := fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)
fmt.Println(d)
}
结果:
22 11
12.00
12.00
16 17 0x10 0x11
printf系列和scanf系列
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
fmt.Println()
fmt.Printf("%v\n",1)
//fmt.Fprintf(f,"%v",1)
s1 := fmt.Sprintf("http://%s/%s","www.baidu.com","/asdf")
fmt.Println(s1)
var m int
var s string
//fmt.Scanf("%d %d",&m,&n)
var line string
f :=bufio.NewReader(os.Stdin)
for {
fmt.Print("> ")
//fmt.Scanln(&line)
line,_=f.ReadString('\n')
fmt.Printf("line:#%s#",line)
fmt.Sscan(line,&s,&m)
//fmt.Scanf("%s %d",&s,&m)
if s == "stop" {
break
}
//fmt.Println(m,n)
fmt.Println(s,m)
}
}
二、字符串相关包:strings和strconv
1.strings.HasPrefix(s string, prefix string) bool:判断字符串s是否以prefix开头 。
练习1:判断一个url是否以http://开头,如果不是,则加上http://。
2.strings.HasSuffix(s string, suffix string) bool:判断字符串s是否以suffix结尾。
练习2:判断一个路径是否以“/”结尾,如果不是,则加上/。
package main
import (
"fmt"
"strings"
)
func urlProcess(url string) string {
res := strings.HasPrefix(url,"http://")
if !res{
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)
}
3.strings.Index(s string, str string) int:判断str在s中首次出现的位置,如果没有出现,则返回-1
4.strings.LastIndex(s string, str string) int:判断str在s中最后出现的位置,如果没有出现,则返回-1
练习3:写一个函数返回一个字符串在另一个字符串的首次出现和最后出现位置func StrIndex(str string, substr string)(int, int){}
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:转为大写
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
str := " hello world greg \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)
}
strconv.Itoa(i int):把一个整数i转成字符串
strconv.Atoi(str string)(int, error):把一个字符串转成整数
类型转换:
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
var all int
for i :=1; i<len(os.Args);i++{
s,err :=strconv.Atoi(os.Args[i])
if err == nil {
all +=s
}
}
fmt.Println("all is ->",all)
}
日期类型
package main
import (
"fmt"
"time"
)
func test() {
time.Sleep(time.Millisecond * 1000)
}
func main() {
now := time.Now()
fmt.Println(now)
fmt.Printf("%02d/%02d/%02d %02d:%02d:%02d\n",
now.Year(),now.Month(),now.Day(),now.Hour(),now.Minute(),now.Second())
fmt.Println(now.Format("2006/01/02 15:04:05"))
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"))
start := time.Now().UnixNano()
test()
end := time.Now().UnixNano()
fmt.Printf("cost:%d us\n", (end-start)/1000)
}
四、指针
1.普通类型,变量存的就是值,也叫值类型;
获取变量的地址,用&,比如: var a int, 获取a的地址:&a
2.指针类型,变量存的是一个地址,这个地址存的才是值;
获取指针类型所指向的值,使用:,比如:var p int, 使用p获取p指向的值。
类似于ln软链接、种子、云链接。
package main
import "fmt"
func modify(p *int) {
fmt.Println(p)
*p = 199
return
}
func main() {
var a int = 10
fmt.Println(&a)
var p *int
p = &a
fmt.Println("p的地址:", &p)
fmt.Println("p-self:", p)
fmt.Println("the value of p point to variable:", *p)
*p = 100
fmt.Println(a)
var b int = 99
p = &b
*p = 9
fmt.Println(a)
fmt.Println(b)
modify(&a)
fmt.Println(a)
}
五、控制语句
1.条件语句:
条件语句不需要使用括号将条件包含起来();
无论语句体内有几条语句,花括号{}都是必须存在的;
左花括号{必须与if或者else处于同一行;
在if之后,条件语句之前,可以添加变量初始化语句,使用;间隔;
在有返回值的函数中,不允许将“最终的” return语句包含在if...else...结构中,
否则会编译失败:
function ends without a return statement。
失败的原因在于, Go编译器无法找到终止该函数的return语句
package main
import (
"fmt"
"strconv"
)
func main() {
var str string
fmt.Scanf("%s", &str)
number, err := strconv.Atoi(str)
if err != nil {
fmt.Println("convert failed, err:", err)
return
}
fmt.Println(number)
}
2.选择语句 switch:
在使用switch结构时,我们需要注意以下几点:
左花括号{必须与switch处于同一行;
条件表达式不限制为常量或者整数;
单个case中,可以出现多个结果选项;
与C语言等规则相反, Go语言不需要用break来明确退出一个case;
只有在case中明确添加fallthrough关键字,才会继续执行紧跟的下一个case;
可以 不设定switch之 后的条 件表达式, 在此种情况 下,整个switch结构与 多个if...else...的逻辑作用等同。
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) != 4 {
fmt.Println("Usage: myexpr 1 + 2")
return
}
x, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
y, err := strconv.Atoi(os.Args[3])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
switch os.Args[2] {
case "+":
fmt.Printf("%v + %v = %v\n", x, y, x+y)
case "-":
fmt.Printf("%v - %v = %v\n", x, y, x-y)
case "*":
fmt.Printf("%v * %v = %v\n", x, y, x*y)
case "/":
fmt.Printf("%v / %v = %v\n", x, y, x/y)
default:
fmt.Println("Usage: myexpr 1 + 2")
}
}
3.循环语句
与多数语言不同的是, Go语言中的循环语句只支持for关键字,而不支持while和do-while结构。关键字for的基本使用方法与C和C++中非常接近。
package main
import (
"fmt"
"os"
)
func main(){
for i:=2;i<len(os.Args);i++{
fmt.Println(os.Args[i])
}
i:=5
fmt.Println("//////////////")
for i <7{
fmt.Println(i)
i=i+1
}
fmt.Println("//////////////")
var j=8
//等价于while true
for {
j=j+1
fmt.Println(j)
if j>10{
break
}
}
fmt.Println("//////////////")
for i,arg := range os.Args{
fmt.Println(i,arg)
}
fmt.Println("//////////////")
s:="hello中文"
for i,arg := range s {
//fmt.Println(i,arg)
fmt.Printf("%d %c\n",i,arg)
}
}
4.goto跳转语句:
label标签:
package main
import "fmt"
func main() {
LABEL1:
for i := 0; i <= 5; i++ {
for j := 0; j <= 5; j++ {
if j == 4 {
continue LABEL1
}
fmt.Printf("i is: %d, and j is: %d\n", i, j)
}
}
}
goto语句:
package main
import "fmt"
func main() {
i := 0
HERE:
fmt.Println(i)
i++
if i == 5 {
return
}
goto HERE
}