GoStudy 练习

原创
2020/07/17 20:46
阅读数 234

1.有一堆数字,如果除了一个数字以外,其他数字都出现了两次,那么如何找到出现一次的数字?

解法1:

var arr = [...]int{1, 2, 3, 4, 5, 4, 2, 1, 5, 2, 1}
var tmp = make([]int, len(arr), len(arr))

for _, v := range arr {
    tmp[v]++;
}
for k, v := range a22 {
    if v == 1 {
        fmt.Println(k,v)
    }
}

解法2:

package main
import "fmt"

func main() {
    nums := [...]int{1, 1, 2, 2, 3, 4, 4}
    res := 0
    for _, v := range nums {
        res ^= v
    }
    fmt.Println(res)
}

任何数和 00 做异或运算,结果仍然是原来的数,即 a ^ 0=aa⊕0=a。s
任何数和其自身做异或运算,结果是 00,即 a ^ a=0a⊕a=0。
异或运算满足交换律和结合律,即 a ^ b ^ a=b ^ a ^ a=b ^ (a ^ a)=b ^ 0=ba⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b。

2.编写代码统计出字符串"学习go语言"中汉字的数量。

解法1:

package main
import (
		"fmt"
)

func main() {
    str := "学习go语言"
    var count int
    ch := []rune(str)
    for _, v := range ch {
        if v > 256  {  // ASCII码0-255
            count++
            fmt.Println(string(v))
        }
        //if len(string(v)) >= 3 {  //UTF8编码下一个中文汉字由3~4个字节组成
        //  	count++
        //}
    }
    fmt.Println(count)
}

解法2:

package main
import (
		"fmt"
)

func main() {
    str := "学习go语言"
    count := 0
    const startCode = 0x2E80  // ^[\u2E80-\u9FFF]+$ 中日韩文字的正则表达式
    const endCode = 0x9FFF
    for _, v := range str {
        if startCode < v && endCode > v {
            count++
            fmt.Println(string(v))
        }
    }
    fmt.Println(count)
}
非英文汉字范围:https://www.cnblogs.com/yunsicai/p/4110522.html

if条件判断

func ifDemo1() {
    score := 65
    if score >= 90 {
      	fmt.Println("A")
    } else if score > 75 {
      	fmt.Println("B")
    } else {
      	fmt.Println("C")
    }
}

func ifDemo2() {
    if score := 65; score >= 90 {
      	fmt.Println("A")
    } else if score > 75 {
      	fmt.Println("B")
    } else {
      	fmt.Println("C")
    }
}
先执行score := 65这一条语句,再根据这个变量值进行判断,它的好处是语句执行完了这个变量就销毁了,对程序来说可以节约程序开销。

3 数组

1 求数组[1, 3, 5, 7, 8]所有元素的和

2 找出数组中和为指定值的两个元素的下标,比如从数组[1, 3, 5, 7, 8]中找出和为8的两个元素的下标分别为(0,3)(1,2)

//求数组[1, 3, 5, 7, 8]所有元素的和
func Sum() {
    a := [5]int{1, 3, 5, 7, 8}
    sum := 0
    for _, i := range a {
      	sum += i
    }
    fmt.Println(sum)
}

//找出数组中和为指定值的两个元素的下标,比如从数组[1, 3, 5, 7, 8]中找出和为8的两个元素的下标分别为(0,3)和(1,2)。
func Find() {
    a := [5]int{1, 3, 5, 7, 8}
    for i, j := range a {
        for l, k := range a[i+1:] {
            if j + k == 8 {
              	fmt.Printf("(%d, %d)  ", i, l+i+1)
            }
        }
    }
}

var num = [...]int{1, 3, 5, 7, 8}
for _, value := range num {
  	for i := 0; i < len(num)/2; i++ {  // 1/2(O*n3)
        if value + num[i] == 8 {
          	fmt.Println(value, num[i])
        }
    }
}

4.请使用内置的sort包对数组var a = [...]int{3, 7, 8, 9, 1}进行排序

package main

import (
    "fmt"
    "sort"
)

func main() {
    var a = [...]int{3, 7, 8, 9, 1}
    b := a[:]
    sort.Ints(b)
    fmt.Println(b)
    sort.Sort(sort.Reverse(sort.IntSlice(b)))
    fmt.Println(b)
}

5 map

1 写一个程序,统计一个字符串中每个单词出现的次数。比如:”how do you do”中how=1 do=2 you=1。

2 观察下面代码,写出最终的打印结果。

1.
package main

import (
    "fmt"
    "strings"
)

func wordCount(words string) map[string]int {
    wordsStr := strings.Split(words, " ")
    m := make(map[string]int, len(wordsStr))
    for _, word := range wordsStr {
        m[word]++
    }
    return m
}
//func wordCount(words string) (m map[string]int) {    给返回值命名
//    wordsStr := strings.Split(words, " ")
//    m = make(map[string]int, len(wordsStr))
//    for _, word := range wordsStr {
//        m[word]++
//    }
//    return
//}

func main() {
    var str = "how do you do"
    //fmt.Println(wordCount(str))
    for k, v := range wordCount(str) {
        fmt.Println(k, v)
    }
}
2.
package main

import (
    "fmt"
)

func main() {
    type Map map[string][]int
    m := make(Map)
    s := []int{1, 2}
    s = append(s, 3)
    fmt.Printf("%+v\n", s)
    m["why"] = s
    fmt.Printf("%+v\n", m["why"])
    s = append(s[:1], s[2:]...)
    fmt.Printf("%+v\n", s)
    fmt.Printf("%+v\n", m["why"])
}

[1 2 3]
[1 2 3]
[1 3]
[1 3 3]  3???

6 分金币

/*
你有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’ 函数
*/

var (
    coins = 50
    users = []string{
      	"Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
    }
    distribution = make(map[string]int, len(users))
)

func main() {
    left := dispatchCoin()
    fmt.Println("剩下:", left)
}
package main

import (
    "fmt"
    "strings"
)

var (
    coins = 50
    users = []string{
      	"Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
    }
    distribution = make(map[string]int, len(users))
)

func main() {
    left := dispatchCoin()
    fmt.Println("剩下:", left)
}

func dispatchCoin() (left int) {
    for _, name := range users {
        coin := countCoin(name)
        distribution[name] = coin
        fmt.Printf("%s 的金币为:%d\n", name, coin)
    }
    result := 0
    for _, value := range distribution {
      	result += value
    }
    fmt.Printf("总使用的金币: %d\n", result)
    return coins - result
}

func countCoin(name string) (result int) {
    if &name != nil {
        name = strings.ToUpper(name)
        bs := []byte(name)
        result = 0
        for _, value := range bs {
            if value == 'E' {
              	result++
            } else if value == 'I' {
              	result += 2
            } else if value == 'O' {
              	result += 3
            } else if value == 'U' {
              	result += 4
            }
        }
        return
    }
    return 0
}
//------------------------
func dispatchCoin() int {
    left := coins
    for _, name := range users {
        e := strings.Count(name, "e") + strings.Count(name, "E")
        i := strings.Count(name, "i") + strings.Count(name, "I")
        o := strings.Count(name, "o") + strings.Count(name, "O")
        u := strings.Count(name, "u") + strings.Count(name, "U")
        sum := e*1 + i*2 + o*3 + u*4
        distribution[name] = sum
        left -= sum
    }
    fmt.Println(distribution)
    return left
}

7 去重

1 slice&map

package main

import (
	"fmt"
)

func RemoveRepByLoop(slc []int) []int{
    var result []int
    for i := range slc {
        flag := false
        for j := range result {
            if slc[i] == result[j] {
                flag = true
                break
            }
        }
        if !flag {
          	result = append(result, slc[i])
        }
    }
    return result
}

func RemoveRepByMap(slc []int) []int {
    var result []int
    tempMap := map[int]byte{}  // 存放不重复主键
    for _, e := range slc {
        l := len(tempMap)
        tempMap[e] = 0
        if len(tempMap) != l {  // 加入map后,map长度变化,则元素不重复
          	result = append(result, e)
        }
    }
    return result
}

func removeDuplicateElement(arr []string) []string {
    result := make([]string, 0, len(arr))
    temp := map[string]struct{}{}
    for _, item := range arr {
        if _, ok := temp[item]; !ok {
            temp[item] = struct{}{}
            result = append(result, item)
        }
    }
    return result
}

// 元素去重
func RemoveRep(slc []int) []int{
    if len(slc) < 1024 {
        // 切片长度小于1024的时候,循环来过滤
        return RemoveRepByLoop(slc)
    } else {
        // 大于的时候,通过map来过滤
        return RemoveRepByMap(slc)
    }
}

func main() {
    arr := []int{6, 3, 5, 4, 3, 2, 1}
    s := []string{"golang", "python", "golang", "JavaScript", "python"}
    fmt.Println(RemoveRep(arr))
    fmt.Println(removeDuplicateElement(s))
}

2 结构体

// setting_string.go  setting_int.go string->int
package utils

import (
    "sort"
    "sync"
)

// 实现 set 集合,变相实现 切片去重
type StringSet struct {
    m map[string]bool
    sync.RWMutex
}

func NewStringSet() *StringSet {
    return &StringSet{
      	m: map[string]bool{},
    }
}

func (s *StringSet) Add(items ...string) {
    s.Lock()
    defer s.Unlock()
    if len(items) == 0 {
      	return
    }
    for _, item := range items {
      	s.m[item] = true
    }
}

func (s *StringSet) Remove(items ...string) {
    s.Lock()
    defer s.Unlock()
    if len(items) == 0 {
        return
    }
    for _, item := range items {
        delete(s.m, item)
    }
}

func (s *StringSet) Has(item string) bool {
    s.RLock()
    defer s.RUnlock()
    _, ok := s.m[item]
    return ok
}

func (s *StringSet) Len() int {
		return len(s.List())
}

func (s *StringSet) Clear() {
    s.Lock()
    defer s.Unlock()
    s.m = map[string]bool{}
}

func (s *StringSet) IsEmpty() bool {
    if s.Len() == 0 {
      	return true
    }
    return false
}

func (s *StringSet) List() []string {
    s.RLock()
    defer s.RUnlock()
    var list []string
    for item := range s.m {
      	list = append(list, item)
    }
    return list
}

func (s *StringSet) SortList() []string {
    s.RLock()
    defer s.RUnlock()
    var list []string
    for item := range s.m {
      	list = append(list, item)
    }
    sort.Strings(list)
    return list
}

//main.go
package main

import (
    "fmt"
    "goTest/utils"
)
func main() {
    // int 集合
    //s := utils.NewIntSet()

    // 添加数据
    //s.Add(5, 2, 4, 3, 5, 6, 7)

    // 去重后的值
    //fmt.Println(s.List())

    // 排序后的值
    //fmt.Println(s.SortList())

    // string 集合
    s2 := utils.NewStringSet()

    // 添加数据
    s2.Add("goland", "python", "study", "goalng", "python", "goland")

    // 去重后的值
    fmt.Println(s2.List())

    // 排序后的值
    fmt.Println(s2.SortList())
}

8 (结构体)使用“面向对象”的思维方式编写一个学生信息管理系统。

1.学生有id、姓名、年龄、分数等信息

2.程序提供展示学生列表、添加学生、编辑学生信息、删除学生等功能

package main

import (
    "fmt"
    "os"
    "sort"
)

type Student struct {
    ID int
    Name string
    Age int8
    Score int8
}

type Class struct {
		Map map[int]*Student
}

//添加学生
func (c *Class) AddStudent() {
    var id int
    var name string
    var age int8
    var score int8
    fmt.Print("输入id: ")
    _, err := fmt.Scan(&id)
    fmt.Print("输入姓名: ")
    _, err = fmt.Scan(&name)
    fmt.Print("输入年龄: ")
    _, err = fmt.Scan(&age)
    fmt.Print("输入分数: ")
    _, err = fmt.Scan(&score)
    if err != nil {
      	fmt.Println("保存出错!")
    }
    _, isSave := c.Map[id]
    if isSave {
        fmt.Println("学生ID已存在!")
        return
    }
    student := &Student{
        ID: id,
        Name: name,
        Age: age,
        Score: score,
    }
    c.Map[id] = student
    fmt.Println("保存成功!")

}

//查看学生列表
func (c *Class) ShowStudent() {
    fmt.Printf("\t%s\t%s\t%s\t%s\n", "ID", "姓名", "年龄", "分数")
    sortID := make([]int, 0)
    for k := range c.Map {
      	sortID = append(sortID, k)
    }
    sort.Ints(sortID)
    for _, k := range sortID {
        s := c.Map[k]
        fmt.Printf("\t%d\t%s\t%d\t%d\n", s.ID, s.Name, s.Age, s.Score)
    }
}

//删除学生
func (c *Class) DeleteStudent() {
    fmt.Print("输入要删除的学生ID:")
    var id int
    _, err := fmt.Scan(&id)
    if err != nil {
      	fmt.Println("ID错误")
    }
    _, isSave := c.Map[id]
    if !isSave {
      	fmt.Println("ID不存在!")
    }
    delete(c.Map, id)
    fmt.Println("删除成功!!")
}

//修改学生信息
func (c *Class) ChangeStudent() {
    fmt.Print("输入要修改的学生ID:")
    var id int
    _, err := fmt.Scan(&id)
    if err != nil {
      	fmt.Println("ID错误")
    }
    var name string
    var age int8
    var score int8
    fmt.Print("输入姓名: ")
    _, err = fmt.Scan(&name)
    fmt.Print("输入年龄: ")
    _, err = fmt.Scan(&age)
    fmt.Print("输入分数: ")
    _, err = fmt.Scan(&score)
    if err != nil {
      	fmt.Println("出错了!")
    }
    student := &Student{
        ID: id,
        Name: name,
        Age: age,
        Score: score,
    }
    c.Map[id] = student
    fmt.Println("修改成功!")
}


func main() {
    c := &Class{}
    c.Map = make(map[int]*Student, 50)
    for {
        fmt.Print("1. 添加  2.查看  3.修改  4.删除 0. 退出\n")
        var todo int8
        _, err := fmt.Scan(&todo)
        if err != nil {
          	fmt.Println("输入有误!")
        }
        switch todo {
        case 1:
          	c.AddStudent()
        case 2:
          	c.ShowStudent()
        case 3:
          	c.ChangeStudent()
        case 4:
          	c.DeleteStudent()
        case 0:
          	os.Exit(-1)
        default:
          	fmt.Println("输入有误!")
        }
    }
}

9 接口

使用接口的方式实现一个既可以往终端写日志也可以往文件写日志的简易日志库。

package main

import (
	"fmt"
	"io"
	"os"
)

type Logger interface {
		Info(string)
}

type FileLogger struct {
		filename string
}

type ConsoleLogger struct {}

/*func (fl *FileLogger) Info(msg string) {
    var f *os.File
    var err error
    if _, err = os.Stat(fl.filename); !os.IsNotExist(err) {
        f, err = os.OpenFile(fl.filename, os.O_APPEND|os.O_WRONLY, 0666)
        fmt.Println("open file!")
    } else {
        f, err = os.Create(fl.filename)
        if err != nil {
          	panic(err)
        }
        fmt.Println("create file!")
    }
    defer f.Close()
    n, err := io.WriteString(f, msg + "\n")
    if err != nil {
      	panic(err)
    }
    fmt.Printf("写入%d个字节\n", n)
}*/

func (fl *FileLogger) Info(msg string) {
    var f *os.File
    var err error
    if checkFileIsExist(fl.filename) {
        f, err = os.OpenFile(fl.filename, os.O_APPEND|os.O_WRONLY, 0666)
        fmt.Println("File Exist!")
    } else {
        f, err = os.Create(fl.filename)
        fmt.Println("File Not Exist!")
    }
    defer f.Close()
    n, err := io.WriteString(f, msg + "\n")
    if err != nil {
      	panic(err)
    }
    fmt.Printf("写入%d个字节\n", n)
}

func checkFileIsExist(filename string) bool {
    if _, err := os.Stat(filename); os.IsNotExist(err) {
      	return false
    }
    return true
}

func (cl *ConsoleLogger) Info(msg string) {
		fmt.Println(msg)
}

func main() {
    var logger Logger
    fileLogger := &FileLogger{"log.txt"}
    logger = fileLogger
    logger.Info("Hello")
    logger.Info("study golang")

    consoleLogger := &ConsoleLogger{}
    logger = consoleLogger
    logger.Info("Hello!")
    logger.Info("study golang!")
}

---------------------------------------------------------------------------

type logSystem interface {
    console(interface{})
    file(interface{})
}
type localLog struct{}

func (l localLog) console(log interface{}) {
    logInfo := log.(string) + "\n"
    _, _ = os.Stdout.WriteString(logInfo)
}
func (l localLog) file(log interface{}) {
    logMsg := log.(string) + "\n"
    filename := "interface.log"
    _, err := os.Stat(filename)
    if err != nil {
        fmt.Println("文件不存在!需要创建!")
        _, err := os.Create(filename)
        if err != nil {
          	panic(err)
        }
        // fmt.Println(err)
        file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_EXCL, 0664) //|os.O_CREATE|os.O_EXCL
        if err != nil {
            // fmt.Println(err)
            fmt.Printf("创建打开文件,报错:%s", err)
        }
        defer file.Close()
        if _, err := file.WriteString(logMsg); err == nil {
          	fmt.Println("写入文件成功!")
        } else {
            // fmt.Println("文件写入报错!")
            // fmt.Println(err)
            fmt.Printf("文件写入报错!,报错信息:%s", err)
        }
    } else {
        fmt.Println("文件存在!")
        // fmt.Println(fileStat)
        file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 066) //|os.O_CREATE|os.O_EXCL
        if err != nil {
          	fmt.Printf("打开文件错误,报错:%s", err)
        }
        defer file.Close()
        if _, err := file.WriteString(logMsg); err == nil {
          	fmt.Println("写入文件成功!")
        } else {
            fmt.Println("文件写入报错!")
            fmt.Println(err)
        }
    }

}

func logger(log string) {
    // log := log
    var logger logSystem
    var application = localLog{}
    logger = application
    logger.console(log)
    logger.file(log)

}
func main() {
    var word string = "study golang!"
    logger(word)
}

10 反射

编写代码利用反射实现一个ini文件的解析器程序。

pass
展开阅读全文
go
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部