GO语言基础
- 高性能,高并发
- 丰富的标准库和完整的工具链
- 静态链接
- 快速编译
- 跨平台(各种操作系统,树莓派等)
- 垃圾回收(无需考虑内存分配释放)
基础语法
变量命名与赋值
- 常量可以不显式指定数据类型,编译器可以根据上下文自动确定
var a = 1
var b int = 2
注意!!!在Go语言中赋值有两种方法:=和:=,其中=只是单纯的赋值,而:=表示声明并赋值,如果变量先前已经声明,则可以直接使用=,否则需使用:=。
条件控制语句
if语句
语法格式如下:
if <bool> {
} else if <bool> {
} else{
}
注意,if后面的bool语句不用打括号,并且else if 和else必须写在上一个大括号的同一行(??)
for语句
在GO语言中,没有while和do while语句,只有for语句,for语句可以缺省任何一部分值,例如
for {
//表示死循环
}
for i:=1;i<10;i++ {
//从1-9的遍历
}
switch语句
switch a{
case 1:
case 2:
default:
}
GO语句在switch之后不需要加break手动破坏,即每次只会执行一个结果。
switch可以使用任意的数据结构,比如
t := time.Now()
switch {
case t.Hour()<12:
default:
}
数组与切片
数组
数组长度是固定的,具有内置的操作函数。
var arr [5]int
fmt.Println(arr[0],len(a))
切片
有点类似Vector,但是不是一个对象len和append函数不能直接使用'.'获取,长度可变的数组,实现方法如下
s := make([]string,3)
fmt.Println(s[0],len(s));
s=append(s,'f')
//选择数组长度的方法
fmt.Println(s[1:5])
fmt.Println(s[:5])
fmt.Println(s[1:])
Map键值对
也就是其它语言中的哈希(HashMap)等数据结构,定义方法如下:
m := make(map[string]int)
range
在不关心某个切片或者数组索引的时候,可以直接遍历里面的元素,写法如下:
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println("sum:", sum)
函数
基本形式为func (结构体示例) <函数名> (函数参数) <返回类型>,具体看结构体方法部分的代码,有给出两种不同的函数体的定义。
指针
//Go语言的指针使用比较简单,就是C++中的指针传递方法,可以用于在函数中修改指针的值,比如
func test(str *string) string{
return str+"。"
}
结构体
//结构体声明
type user struct{
name string
psw string
}
//结构体初始化
a:=user(name:"Veni",psw:"1111")
a:=user("Veni","1111")
结构体方法
结构体方法类似C++中的类成员函数,定义方法:
//非结构体方法的函数定义:
func checkPassword(u user,password string) bool{
return u.password==password
}
//结构体方法的函数定义
func (u user) checkPassword(password string) bool{
return u.password==password
}
fmt.Println(a.checkPassword("1111"))//return true or false
错误处理
在函数返回值的时候可以定义返回值err,同时return两个值,比如
func findUser(users []user,name string)(v *user,err error){
for _,u :=range users{
if(u.name==name){
return &u,nil
}
}
return nil,error.New("Not Found")
}
字符串函数
OJ必备,用好了可以提高效率
字符串操作函数
import{
"strings"
}
func main(){
a:="hello"
strings.Contains(a,"ll")//true
strings.Count(a,"l") //2
strings.HasPrefix(a,"he")//true
strings.HasSuffix(a."llo")//true
strings.Index(a,"ll")//2
strings.Repeate(a,2)//hellohello
strings.Replace(a,"e","E",-1)//hEllo
strings.Split("a-b-c","-")//[a b c]
strings.ToLower(a)//hello
strings.ToUpper(a)//HELLO
}
字符串格式化
fmt.Printf("s=%v\n",p) //%v可以是任意类型的占位符
fmt.Printf("s=%+v\n",p)
fmt.Printf("s=%#v\n",p) //更加详细的信息
fmt.Printf("s=%.2f\n",3.1415)
数字解析
引入strconv包
n,_ :=strconv.ParseInt("111",10,64)
n1,_ :=strconv.Atoi("111")
Json操作
只需要定义一个结构体,结构体的首字母需要大写,之后就可以直接进行序列化。
type userInfo struct{
Name string
Age int `json:"age"` //将字段名改成小写的age,一般不加这一段
Hobby []string
}
//序列化
buf,err :=json.Marshal(a)
jmt.Println(string(buf)) //打印json,记得加string,不然会打印出一堆十六进制编码
//反序列化
var b userInfo
err=json.Unmarshal(buf,&b)
时间处理
需要import time,可以直接查文档。最常用的是获取当前时间:
t:=time.Now()
进程信息
使用GO语言可以查看进程的相关信息,具体可以查看文档。
输入输出
输入的几种方法
使用fmt包
- 格式化扫描输入
// 从 控制台(os.Stdin) 扫描输入
var a int
fmt.Scan(&a) // 输入: 123<回车>
fmt.Println(a) // 输出: 123
var b int
var s string
fmt.Scan(&b, &s) // 输入: 123 Hello<回车>
fmt.Println(b, s) // 输出: 123 Hello
// 从 字符串(string) 扫描输出
fmt.Sscan("456", &a)
fmt.Println(a) // 输出: 456
fmt.Sscan("456 World", &b, &s)
fmt.Println(b, s) // 输出: 456 World
- 格式化扫描输入
// 从 控制台(os.Stdin) 格式化扫描输入
var a int
fmt.Scanf("%d", &a) // 输入: 123<回车>
fmt.Println(a) // 输出: 123
var b int
var s string
fmt.Scanf("%d%s", &b, &s) // 输入: 123 Hello<回车>
fmt.Println(b, s) // 输出: 123 Hello
// 从 字符串(string) 格式化扫描输出
fmt.Sscanf("456", "%d", &a)
fmt.Println(a) // 输出: 456
fmt.Sscanf("456 World", "%d%s", &b, &s)
fmt.Println(b, s) // 输出: 456 World
事实上,%d%s只是用来格式化的一个占位符,在GO语言中可以使用%v代替,没怎么写过C语言的选手也可以用好Scanf啦!
从标准输入(os.Stdin)直接读取数据
// 创建 字节切片 用于保存读取到的字节序列
buf := make([]byte, 10)
// 等待从 控制台(os.Stdin) 输入数据, 按回车键触发读取,
// 最多读取 len(buf) 个字节,
// 回车符(\n)也算作是输入的数据, 也会被读取,
// 读取的字节序列是经过 UTF-8 编码的字节序列,
// 返回的 n 表示本次读取的字节数
n, err := os.Stdin.Read(buf)
fmt.Println(n, err)
// 转换为字符串输出
fmt.Printf("%s", string(buf[:n]))
使用bufio.Scanner扫描器读取数据
// 创建一个扫描器对象, 从 os.Stdin 中扫描数据
scan := bufio.NewScanner(os.Stdin)
// 阻塞等待输入, 输入数据后, 按回车触发扫描, Scan() 返回 true
if scan.Scan() {
// 以 (UTF-8)字符串 的形式读取本次扫描的数据 (支持输入空格, 不包括换行符, 换行符自动舍去)
s := scan.Text()
fmt.Printf("%s\n", s)
}
// 继续阻塞等待下次输入
if scan.Scan() {
// 以 (UTF-8)字节切片 的形式读取本次扫描的数据
b := scan.Bytes()
fmt.Printf("%s\n", string(b))
}
字节训练营中的一段bug码,在这段代码中会读取换行符和回车键\r\n,需要手动去除。
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("输入错误,请重新输入")
return
}
input = strings.Trim(input, "\r")
input = strings.Trim(input, "\n")
一般的输入输出还是用Scan好一点,如果做OJ写成上面那样真的会疯掉。