day01
请获取字符串"hello我要杀了你这头猪",中有多少个中文。
字符和字节和字符串
go语言,字符串有一个特点,不能修改。
字符:用单引号包裹,单个字母,单个符号,单个文字
字符串:用双引号包裹。
字节:1byte=8bit
go语言中字符串都是UTF8编码,UTF8编码中一个汉字一般占用3个字节
Go 语言的内建函数 len(),可以用来获取切片、字符串、通道(channel)等的长度。下面的代码可以用 len() 来获取字符串的长度。
s := “hello我要杀了你这头猪”
fmt.Println(len(s))
29
go 语言写法:
package main
import (
"fmt"
"unicode"
)
func main() {
s := "hello我要杀了你这头猪"
chNum := 0
for _, v := range s {
if unicode.Is(unicode.Han, v) {
chNum ++
}
}
fmt.Println(chNum)
}
对应Python写法:
def main():
s = "hello我要杀了你这头猪"
num = 0
for i in s:
s_len = len(i.encode('utf-8'))
print(s_len)
if s_len == 3:
num += 1
return num
if __name__ == '__main__':
ch_num = main()
print(ch_num)
输出99乘法表
循环遍历的问题
go 语言写法:
package main
import "fmt"
func main() {
for i := 1; i < 10; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d * %d = %d ", j, i, i*j)
}
fmt.Println()
}
}
对照Python写法
def main():
for i in range(1, 10):
for j in range(1, 10):
if i >= j:
# python默认print中end='\n'也就是自带换行,取消自动换行:end='',
print("%d * %d = %d " % (i, j, i * j), end='')
print()
if __name__ == '__main__':
main()
def main():
for i in range(1, 10):
w = 10 - i
for j in range(w, 10):
print("%d * %d = %d " % (j - w + 1, i, i * (j - w + 1)), end='')
print()
if __name__ == '__main__':
main()
day02
计算字符串中"how do you do"每个单词出现的次数。
分析:首先把字符串切开,然后再使用map进行统计,当某个单词已经存在的时候,其对应的值自动加一。
使用go
package main
import (
"fmt"
"strings"
)
func main() {
newStr := "how do you do"
s1 := strings.Split(newStr, " ")
m1 := make(map[string]int, 10)
for _, v := range s1 {
if m1[v] != 0 {
m1[v] = m1[v] + 1
} else {
m1[v] = 1
}
}
for k, v := range m1 {
fmt.Println(k, v)
}
}
使用python
s1 = "how do you do"
def main():
s1_list = s1.split(' ')
s1_map = {}
for i in s1_list:
s1_map[i] = s1_map[i] + 1 if s1_map.get(i) else 1
for k, v in s1_map.items():
print(k, v)
if __name__ == '__main__':
main()
day03
分金币
你有50枚金币,需要分配给以下几个人:Matthew,Sarah,Augustus,Heidi,Emilie,Peter,Giana,Adriano,Aaron,Elizabeth。
分配规则如下:
a. 名字中每包含1个’e’或’E’分1枚金币
b. 名字中每包含1个’i’或’I’分2枚金币
c. 名字中每包含1个’o’或’O’分3枚金币
d: 名字中每包含1个’u’或’U’分4枚金币
写一个程序,计算每个用户分到多少金币,以及最后剩余多少金币?
程序结构如下,请实现 ‘dispatchCoin’ 函数
package main
import "fmt"
var (
coins = 50
users = []string{
"Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
}
distribution = make(map[string]int, len(users))
)
func dispatchCoin() interface{} {
for _, name := range users {
nextCoins := coins
for _, b := range name {
switch b {
case 'e', 'E':
coins -= 1
case 'i', 'I':
coins -= 2
case 'o', 'O':
coins -= 3
case 'u', 'U':
coins -= 4
}
}
distribution[name] = nextCoins - coins
}
fmt.Println(distribution)
return coins
}
func main() {
left := dispatchCoin()
fmt.Println("剩下:", left)
}
使用python
name_list = ["Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth"]
coins = 50
def dispatch_coin(the_list, start_coins):
name_map = {}
for name in the_list:
left_coins = start_coins
for p in name:
if p in ["e", "E"]:
start_coins -= 1
elif p in ["i", "I"]:
start_coins -= 2
elif p in ["o", "O"]:
start_coins -= 3
elif p in ["u", "U"]:
start_coins -= 4
else:
pass
name_map[name] = left_coins - start_coins
print(name_map)
return start_coins
def main():
left = dispatch_coin(name_list, coins)
print(left)
if __name__ == '__main__':
main()
day04
面试题走台阶
假设有一段台阶,可以每次走一个,也可以每次走2个,那么一共有多少种走法。
递归。
package main
import "fmt"
func taijie(n uint64) uint64 {
// 如果有一个台阶毫无疑问就是一种
if n == 1 {
return 1
}
// 如果有2个台阶,那有两种方法。
if n == 2 {
return 2
}
// 假设走到最后一步的时候,此时只有2种情况,那就是还有一个台阶或者还有2个台阶
// 那么把走剩最后一步的前面走台阶的方式加在一起就是全部的走法
return taijie(n-1) + taijie(n-2)
}
func main() {
way := taijie(5)
fmt.Printf("共有%d种走法", way)
}
python的写法
def tai_jie(n):
if n == 1:
return 1
if n == 2:
return 2
return tai_jie(n - 1) + tai_jie(n - 2)
def main(n):
ways = tai_jie(n)
print("一共有%d种方法"% ways)
if __name__ == '__main__':
main(5)
写一个学生管理系统函数版:
package main
import (
"fmt"
"os"
)
/*
写一个学生系统,不需要做多余的判断,考验结构体的使用。
*/
type studentInfo struct {
id uint32
name string
}
var studentMap map[uint32]*studentInfo
func xiTong() {
fmt.Println("欢迎来到学生系统!!")
// 初始化学生数据
studentMap = make(map[uint32]*studentInfo, 50)
for {
fmt.Println(`
1. 查询
2. 数据添加
3. 数据删除
4. 退出
`)
fmt.Print("请输入序列号:")
var num uint
fmt.Scanln(&num)
switch num {
case 1:
showAllStudent()
case 2:
addStudent()
case 3:
deleteStudent()
case 4:
os.Exit(1)
default:
println("输入错误")
}
}
}
func deleteStudent() {
fmt.Println("删除学生信息")
var id uint32
fmt.Println("请输入删除学生学号:")
fmt.Scanln(&id)
delete(studentMap, id)
}
func addStudent() {
fmt.Println("添加学生信息")
var id uint32
var name string
fmt.Println("请输入学号:")
fmt.Scanln(&id)
fmt.Println("请输入姓名:")
fmt.Scanln(&name)
p := &studentInfo{
id: id,
name: name,
}
studentMap[id] = p
fmt.Println(studentMap)
}
func showAllStudent() {
fmt.Println("学生数据如下:")
for i, v := range studentMap {
fmt.Printf("学号:%d, 姓名:%s\n", i, v.name)
}
}
func main() {
xiTong()
}
面向对象对上一个代码进行更改
package main
import (
"fmt"
"os"
)
type xiTong struct {
studentInfo
studentMap map[uint32]*studentInfo
}
type studentInfo struct {
id uint32
name string
}
//newStudentInfo 是studentInfo类型的构造函数
func (x xiTong) newStudentInfo(id uint32, name string) *studentInfo {
return &studentInfo{
id: id,
name: name,
}
}
func (x xiTong) showAllStudents() {
fmt.Println("学生数据如下:")
for i, v := range x.studentMap {
fmt.Printf("学号:%d, 姓名:%s\n", i, v.name)
}
}
func (x xiTong) addStudent() {
fmt.Println("添加学生信息")
var id uint32
var name string
fmt.Println("请输入学号:")
fmt.Scanln(&id)
fmt.Println("请输入姓名:")
fmt.Scanln(&name)
p := x.newStudentInfo(id, name)
x.studentMap[id] = p
fmt.Println(x.studentMap)
}
func (x xiTong) deleteStudent() {
fmt.Println("删除学生信息")
var deleteID uint32
fmt.Println("请输入删除学生学号:")
fmt.Scanln(&deleteID)
delete(x.studentMap, deleteID)
}
func start() {
fmt.Println("欢迎来到学生系统!!")
// 初始化系统
var x xiTong
// 初始化学生数据
x.studentMap = make(map[uint32]*studentInfo, 50)
for {
fmt.Println(`
1. 查询
2. 数据添加
3. 数据删除
4. 退出
`)
fmt.Print("请输入序列号:")
var num uint
fmt.Scanln(&num)
switch num {
case 1:
x.showAllStudents()
case 2:
x.addStudent()
case 3:
x.deleteStudent()
case 4:
os.Exit(1)
default:
println("输入错误")
}
}
}
func main() {
start()
}
new和make的区别
二者都是用来做内存分配的。
make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。
序列化和反序列化的问题
当将一个对象转换为json的字符串的时候,我们需要用的go的序列化函数:json.Marshal(p1)
序列化:传入一个对象,比如一个结构体。此时我们调用的Marshal函数是json包的函数,传入的内容必须符合go语言要求的外部调用,首字母大写的方式。外部包的调用,被调用的变量首字母大写
反序列话:传入一个字符串,转换成一个结构体,此时调用json.Unmarshal,先初始化一个空结构体,然后将字符串序列化后传入,此时就需要改变原来的空结构体,由于函数传参传入的是参数副本,因此此时只有传入参数的指针,才可以修改需要被填入数据的空结构体。
函数传入参数,参数不是其本身,而是该参数拷贝的一个副本,如果需要进行修改操作,传入的参数必须为一个指针类型
如下例:
package main
import (
"encoding/json"
"fmt"
)
func main() {
type point struct {
// 这里的结构体内部变量名称必须要首字母大写,因为首字母大写才能被外部函数获取到,如果要求输出格式,那就在后面添加:`json:"变量名"`
X int `json:"x"`
Y int `json:"y"`
}
p1 := point{100, 200,}
// 序列化:这个函数返回2个值,0是byte类型的切片,1是报错信息
b, err := json.Marshal(p1)
if err != nil{
fmt.Printf("序列化出错了,err:%s",err)
}
fmt.Println(string(b))
// 反序列化
str1 := `{"x":10,"y":20}`
var p2 point
// 此时要将p2的指针传给函数,这样才能真正的把反序列化后的数据写入到要p2中
err = json.Unmarshal([]byte(str1), &p2)
if err != nil {
fmt.Printf("反序列化出错了:%s", err)
}
fmt.Println(p2)
}
day05
1.写一个copy操作
package main
import (
"fmt"
"io"
"os"
)
func main() {
err := myCopy("1.txt", "2.txt")
if err != nil {
fmt.Println("copy file failed, err:", err)
return
}
fmt.Println("copy finish!")
}
func myCopy(srcName string, dstName string) (err error) {
// 读取数据
src, err := os.Open(srcName)
if err != nil {
fmt.Printf("read file failed, err:%s", err)
return
}
defer src.Close()
// 准备被写入数据的文件
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
fmt.Printf("write file failed, err:%s", err)
return
}
defer dst.Close()
// 调用io.copy进行数据拷贝
io.Copy(dst, src)
return
}
2.模拟编写一个linux的cat操作文件。
写好之后,使用go build创建一个文件叫cat 然后执行:cat 文件1 文件2
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
)
func useBufio() {
reader := bufio.NewReader(os.Stdin)
readString, _ := reader.ReadString('\n')
fmt.Println(readString)
}
func main() {
// 1.从命令行获取到需要被cat的文件名称
flag.Parse() //解析执行该文本的参数,多个参数用空格分开
// 如果默认参数为0,则从标准输入获取内容
if flag.NArg() == 0 {
cat(bufio.NewReader(os.Stdin))
}
// 如果有多个参数,则,逐一打开
for _, fileName := range flag.Args() {
file, err := os.Open(fileName)
if err != nil {
// 输出到命令行
fmt.Fprintf(os.Stdout, "reading %s failed, err:%s\n", fileName, err)
continue
}
cat(bufio.NewReader(file))
}
}
func cat(r *bufio.Reader) {
// 2.打开文件
for {
readString, err := r.ReadString('\n')
if err == io.EOF {
// 上面设定是\n换行,如果最后一行没有输入换行符,即光标在行末,防止本行数据就会丢失
if len(readString) != 0 {
fmt.Print(readString)
}
break
}
if err != nil {
fmt.Printf("file read err:%s\n", err)
break
}
// 将要cat的信息输出到命令行
fmt.Fprintf(os.Stdout, "%s", readString)
}
fmt.Println()
}