欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Go练习题(9)

程序员文章站 2022-07-01 19:11:15
...

在之前的用户管理的基础上使用Json做持久化
目录节构都一致
Go练习题(9)

方法一:

//main.go
package main

import (
	"fmt"
	"github.com/strive-after/users/lib"
)

func main() {
	var (
		user string
		menu string
	)
	if !lib.Auth() {
		fmt.Println("您输入的密码错误,系统退出")
		return
	}
	for {
		//界面打印
		menu = `====================
欢迎使用用户管理系统
====================
1.添加用户
2.查找用户
3.修改用户
4.删除用户
5.修改密码
6.退出程序
====================`
		fmt.Println(menu)
		//用户选择
		user = lib.Inputstring("请输入指令:")
		fmt.Println("====================")
		if user == "1" {
			lib.Add(lib.GetId())
		} else if user == "2" {
			lib.Sel()
		} else if user == "3" {
			lib.Change()
		} else if user == "4" {
			lib.Del()
		} else if user == "5" {
			lib.SetPassword()
		}else if user == "6"{
			break
		} else {
			fmt.Println("输入有误请重新输入")
			continue
		}
	}
}
//load&save.go
package lib

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"time"
)

const userpath string = "./user.json"
//存储用户信息


func SaveUser(UserInfo map[int]User) {
	//对文件重命名 加时间后缀
	if _,err := os.Stat(userpath); err == nil{
	//	//os.Rename(userpath,fmt.Sprintf("%x",time.Now())+".user.csv")
		os.Rename(userpath,strconv.FormatInt(time.Now().Unix(),10)+".user.json")
	}
	//删除文件 保留3个最新的
	if filebak,err := filepath.Glob("*.user.json");err == nil{
	//	//默认是升序 我们要保留最新的 就用倒叙的方式排序 删除3个以后的ok
		sort.Sort(sort.Reverse(sort.StringSlice(filebak)))
		//fmt.Println(filebak)
		if len(filebak) >= 3 {
			for _,v := range  filebak[3:]{
				os.Remove(v)
			}
		}
	}
	if file,err := os.Create(userpath);err == nil {
		defer file.Close()
		encode := json.NewEncoder(file)
		//格式化
		encode.SetIndent("","\t")
		encode.Encode(UserInfo)
	}
}

//加载用户信息
func   LoadUser() map[int]User {
	UserInfo := map[int]User{}
	//判断文件是否存在
	if file,err := os.Open(userpath);err == nil {
		defer  file.Close()
		//创建解码器
		decode := json.NewDecoder(file)
		//将流中的数据编码到对象中  这里UserInfo 是对象 要取指针
		decode.Decode(&UserInfo)
	}else {     //这里err != nil
		if !os.IsNotExist(err) {    //如果不是因为文件不存在 打印报错
			fmt.Printf("[-]发生错误%v",err)
		}
	}
	return  UserInfo
}
//import.go
package lib

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

//因为需要用户输入的比较多定义一个input函数
func Inputstring(input string) string {
	//这里使用带缓冲的io
	//创建scanner
	scanner := bufio.NewScanner(os.Stdin)
	fmt.Printf(input)
	//获取用户信息
	scanner.Scan()
	//返回读取的行信息  text每次读一行
	return strings.TrimSpace(scanner.Text())
}

func Inputuser(id int) {
	UserInfo := LoadUser()
	var user User
	var err error
START:
	user.ID = id
	user.Name = Inputstring("请输入名字:")
	user.Birthday,err = time.Parse("2006-1-2",Inputstring("请输入生日(如2006-1-2):"))
	user.Tel = Inputstring("请输入联系方式:")
	user.Addr = Inputstring("请输入住址:")
	user.Desc = Inputstring("请输入备注:")
	if err == nil {
		for k,v := range UserInfo {
			if  k == id {
				break
			}else if v.Name == user.Name {
				fmt.Println("用户已存在,请重新输入")
				fmt.Println(strings.Repeat("-", 20))
				goto  START
			}else if user.Name == ""{
				fmt.Println("用户名不能为空,请重新输入")
				goto START
			}
		}
		UserInfo[id] = user
		SaveUser(UserInfo)
	}else {
		fmt.Println("格式有误,请重新输入")
		goto START
	}
}
//auth.go
package lib

import (
	"crypto/md5"
	"fmt"
	"io/ioutil"
	"os"
	"time"
	"github.com/howeyc/gopass"
)

//定义密码输入次数
//定义用户结构体
type User struct {
	ID int `json:"id"`
	Name  string `json:"name"`
	Birthday time.Time `json:"birthday"`
	Tel string `json:"tel"`
	Addr string `json:"addr"`
	Desc string `json:"desc"`
}



const (
	passwordFile  = "./passworld"
	maxauth = 3
)
func GetId() int {
	var id int
	UserInfo := LoadUser()
	for  k,_  := range UserInfo {
		if id < k {
			id = k
		}
	}
	return id + 1
}
//使用系统前输入密码 超过3次则退出系统
func Auth() bool {
	//password, err := os.Open(passwordFile)
	password ,err := ioutil.ReadFile(passwordFile)
	//打开密码文件如果err!=nil 就是说打开有问题
	if err != nil || len(password) < 1 {
		//如果是因为不存在 那么我们需要初始化密码
		if os.IsNotExist(err) || len(password) < 1 {
			fmt.Print("请输入初始化密码:")
			bytes, _ := gopass.GetPasswd()
			//将用户输入的密码md5加密  写入文件
			ioutil.WriteFile(passwordFile, []byte(fmt.Sprintf("%x",md5.Sum(bytes))), 0644)
			return true
		} else { //如果不是因为不存在  那么打印报错信息
			fmt.Println(err)
		}
	} else { //如果存在 那么就需要做密码验证
		//defer  password.Close()
		for i := 1; i <= maxauth; i++ {
			// user := Inputstring("请输入密码:")
			fmt.Printf("请输入密码:")
			bytes, _ := gopass.GetPasswd()
			//这里对输入的密码进行md5加密并且与常量比较
			//%x是小写十六进制表示 Sprintf格式化返回一个字符串
			passwd ,_:= ioutil.ReadFile(passwordFile)
			if fmt.Sprintf("%x", md5.Sum(bytes)) == string(passwd) {
				return true
			} else {
				fmt.Printf("输入错误请重新输入,您还有%d次机会\n", maxauth-i)
			}
		}
		return false
	}
	return false
}


func SetPassword() {
	fmt.Printf("请输入旧密码:")
	bytes, _ := gopass.GetPasswd()
	if passwd ,_:= ioutil.ReadFile(passwordFile);string(passwd) == fmt.Sprintf("%x",md5.Sum(bytes)){
		fmt.Print("请输入新密码")
		bytes, _ := gopass.GetPasswd()
		ioutil.WriteFile(passwordFile, []byte(fmt.Sprintf("%x",md5.Sum(bytes))), 0644)
		fmt.Println("密码修改成功")
	}else {
		fmt.Println("密码输入错误")
	}
}
//add.go
package lib

import "fmt"

//添加用户
func Add(id int) {
	Inputuser(id)
	fmt.Println("[+]添加成功")
}
//修改用户
//change.go
package lib

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

func Change() {
	UserInfo := LoadUser()
	if id, err := strconv.Atoi(Inputstring("请输入修改的用户id:")); err == nil {
		fmt.Println(strings.Repeat("-", 20))
		if user, ok := UserInfo[id]; ok {
			fmt.Printf("ID:%d\nname:%s\nbirthday:%v\ntel:%s\naddr:%s\ndesc:%s\n",user.ID, user.Name,user.Birthday.Format("2006-1-2"),user.Tel,user.Addr,user.Desc)
			fmt.Println(strings.Repeat("-", 20))
			affirm := Inputstring("确认是否修改(Y/N):")
			if affirm == "Y" || affirm == "y" {
				Inputuser(id)
			}
		} else {
			fmt.Println("用户id不存在")
		}
	} else {
		fmt.Println("输入错误")
	}
}
//查询用户
//sel.go
package lib

import (
	"fmt"
	"sort"
	"strings"
)

func Sel() {
	UserInfo := LoadUser()
	user := Inputstring("请输入要查询的信息:")
	list := make([]User,0)
	fmt.Println(strings.Repeat("-", 20))
	for _, v := range UserInfo {
		if strings.Contains(v.Name, user) || strings.Contains(v.Desc, user) || strings.Contains(v.Addr, user) || strings.Contains(v.Tel, user) || strings.Contains(v.Birthday.Format("2006-01-02"), user)  {
			list = append(list,v)
		}
	}
	users := Inputstring("请输入要排序的属性(ID,Name,Desc,Addr,Tel,Birthday):")
	sort.Slice(list, func(i, j int) bool {
		switch users {
		case "ID":
			return  list[i].ID < list[j].ID
		case "Name":
			return  list[i].Name < list[j].Name
		case "Desc":
			return  list[i].Desc < list[j].Desc
		case "Addr":
			return  list[i].Addr < list[j].Addr
		case "Tel":
			return  list[i].Tel < list[j].Tel
		case "Birthday":
			return  list[i].Birthday.Format("2006-1-2") < list[j].Birthday.Format("2006-1-2")
		default:
			return list[i].ID < list[j].ID
		}
	})
	for _,v := range  list {
		fmt.Printf("ID:%d\nname:%s\nbirthday:%v\ntel:%s\naddr:%s\ndesc:%s\n", v.ID,v.Name,v.Birthday.Format("2006-1-2"),v.Tel,v.Addr,v.Desc)
		fmt.Println(strings.Repeat("-", 20))
	}


}
//del.go
//删除用户
package lib

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

func Del() {
	UserInfo := LoadUser()
	if id, err := strconv.Atoi(Inputstring("请输入删除的用户id:")); err == nil {
		fmt.Println(strings.Repeat("-", 20))
		if user, ok := UserInfo[id]; ok {
			fmt.Printf("ID:%d\nname:%s\nbirthday:%v\ntel:%s\naddr:%s\ndesc:%s\n",user.ID ,user.Name,user.Birthday.Format("2006-1-2"),user.Tel,user.Addr,user.Desc)
			fmt.Println(strings.Repeat("-", 20))
			affirm := Inputstring("确认是否删除(Y/N):")
			if affirm == "Y" || affirm == "y" {
				delete(UserInfo, id)
				SaveUser(UserInfo)
				fmt.Println("[-]删除成功")
			}
		} else {
			fmt.Println("用户id不存在")
		}
	} else {
		fmt.Println("输入错误")
	}
}

方法二:

//main.go
package main

import (
	"flag"
	"fmt"
	"github.com/strive-after/users/lib"
	"os"
)

func main() {

	var (
		user string
		menu string
	)
	path := flag.String("T","json","json or gob")
	help := flag.Bool("h",false,"help")
	flag.Usage = func() {
		fmt.Println("-T [json/gob]")
	}
	flag.Parse()
	if *help {
		flag.Usage()
		flag.PrintDefaults()
		os.Exit(0)
	}

	lib.GetPeristence(*path)

	if !lib.Auth() {
		fmt.Println("您输入的密码错误,系统退出")
		return
	}


	for {
		//界面打印
		menu = `====================
欢迎使用用户管理系统
====================
1.添加用户
2.查找用户
3.修改用户
4.删除用户
5.修改密码
6.退出程序
====================`
		fmt.Println(menu)
		//用户选择
		user = lib.Inputstring("请输入指令:")
		fmt.Println("====================")
		if user == "1" {
			lib.Add(lib.GetId())
		} else if user == "2" {
			lib.Sel()
		} else if user == "3" {
			lib.Change()
		} else if user == "4" {
			lib.Del()
		} else if user == "5" {
			lib.SetPassword()
		}else if user == "6"{
			break
		} else {
			fmt.Println("输入有误请重新输入")
			continue
		}
	}
}

package lib

import (
“encoding/gob”
“encoding/json”
“fmt”
“os”
“path/filepath”
“sort”
“strconv”
“time”
)

//load&save.go
//存储用户信息
type Users  map[int]User

type JsonPath struct {
	name string
}


type GobPath struct {
	name string
}


type Persistence interface {
	LoadUser() (map[int]User)
	SaveUser(map[int]User)
	NewPath() string
}

var Persi Persistence

func GetPeristence(name string) {
	switch name {
	case "gob" :
		Persi = GobPath{"user.gob"}
	case "json":
		Persi = JsonPath{"user.json"}
	default:
		Persi = JsonPath{"user.json"}
	}
}

func (jsonPath JsonPath) NewPath() string {
	jsonPath.name = "user.json"
	return  jsonPath.name
}

func (gobpath GobPath) NewPath() string {
	gobpath.name = "user.gob"
	return  gobpath.name
}


func (jsonpath JsonPath)SaveUser(UserInfo map[int]User) {
	//对文件重命名 加时间后缀
	if _,err := os.Stat(Persi.NewPath()); err == nil{
		os.Rename(Persi.NewPath(),strconv.FormatInt(time.Now().Unix(),10)+Persi.NewPath())
	}
	//删除文件 保留3个最新的
	if filebak,err := filepath.Glob("*.user.gob");err == nil{
	//	//默认是升序 我们要保留最新的 就用倒叙的方式排序 删除3个以后的ok
		sort.Sort(sort.Reverse(sort.StringSlice(filebak)))
		//fmt.Println(filebak)
		if len(filebak) >= 3 {
			for _,v := range  filebak[3:]{
				os.Remove(v)
			}
		}
	}
	if file,err := os.Create(Persi.NewPath());err == nil {
		defer file.Close()
		encode := json.NewEncoder(file)
		encode.SetIndent("","\t")
		encode.Encode(UserInfo)
	}
}

//加载用户信息
func  (jsonpath JsonPath) LoadUser() (map[int]User) {
	UserInfo := map[int]User{}
	//判断文件是否存在
	if file,err := os.Open(Persi.NewPath());err == nil {
		defer  file.Close()
		//创建解码器
		decode := json.NewDecoder(file)
		//将流中的数据编码到对象中  这里UserInfo 是对象 要取指针
		decode.Decode(&UserInfo)
	}else {     //这里err != nil
		if !os.IsNotExist(err) {    //如果不是因为文件不存在 打印报错
			fmt.Printf("[-]发生错误%v",err)
		}
	}
	return  UserInfo
}


func (gobpath GobPath)SaveUser(UserInfo map[int]User) {
	//对文件重命名 加时间后缀
	if _,err := os.Stat(Persi.NewPath()); err == nil{
		//	//os.Rename(userpath,fmt.Sprintf("%x",time.Now())+".user.csv")
		os.Rename(Persi.NewPath(),strconv.FormatInt(time.Now().Unix(),10)+".user.gob")
	}
	//删除文件 保留3个最新的
	if filebak,err := filepath.Glob("*.user.gob");err == nil{
		//	//默认是升序 我们要保留最新的 就用倒叙的方式排序 删除3个以后的ok
		sort.Sort(sort.Reverse(sort.StringSlice(filebak)))
		//fmt.Println(filebak)
		if len(filebak) >= 3 {
			for _,v := range  filebak[3:]{
				os.Remove(v)
			}
		}
	}
	if file,err := os.Create(Persi.NewPath());err == nil {
		defer file.Close()
		encode := gob.NewEncoder(file)
		encode.Encode(UserInfo)
	}
}

//加载用户信息
func  (gopath GobPath) LoadUser() map[int]User {
	UserInfo := map[int]User{}
	//判断文件是否存在
	if file,err := os.Open(Persi.NewPath());err == nil {
		defer  file.Close()
		//创建解码器
		decode := gob.NewDecoder(file)
		//将流中的数据编码到对象中  这里UserInfo 是对象 要取指针
		decode.Decode(&UserInfo)
	}else {     //这里err != nil
		if !os.IsNotExist(err) {    //如果不是因为文件不存在 打印报错
			fmt.Printf("[-]发生错误%v",err)
		}
	}
	return  UserInfo
}
//import.go
package lib

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

//因为需要用户输入的比较多定义一个input函数
func Inputstring(input string) string {
	//这里使用带缓冲的io
	//创建scanner
	scanner := bufio.NewScanner(os.Stdin)
	fmt.Printf(input)
	//获取用户信息
	scanner.Scan()
	//返回读取的行信息  text每次读一行
	return strings.TrimSpace(scanner.Text())
}

func Inputuser(id int) {
	UserInfo := Persi.LoadUser()
	var user User
	var err error
START:
	user.ID = id
	user.Name = Inputstring("请输入名字:")
	user.Birthday,err = time.Parse("2006-1-2",Inputstring("请输入生日(如2006-1-2):"))
	user.Tel = Inputstring("请输入联系方式:")
	user.Addr = Inputstring("请输入住址:")
	user.Desc = Inputstring("请输入备注:")
	if err == nil {
		for k,v := range UserInfo {
			if  k == id {
				break
			}else if v.Name == user.Name {
				fmt.Println("用户已存在,请重新输入")
				fmt.Println(strings.Repeat("-", 20))
				goto  START
			}else if user.Name == ""{
				fmt.Println("用户名不能为空,请重新输入")
				goto START
			}
		}
		UserInfo[id] = user
		Persi.SaveUser(UserInfo)
	}else {
		fmt.Println("格式有误,请重新输入")
		goto START
	}
}
//auth.go
package lib

import (
	"crypto/md5"
	"fmt"
	"io/ioutil"
	"os"
	"time"
	"github.com/howeyc/gopass"
)

//定义密码输入次数
//定义用户结构体
type User struct {
	ID int
	Name  string
	Birthday time.Time
	Tel string
	Addr string
	Desc string
}


const (
	passwordFile  = "./passworld"
	maxauth = 3
)

func GetId() int {
	var id int
	UserInfo := Persi.LoadUser()
	for  k,_  := range UserInfo {
		if id < k {
			id = k
		}
	}
	return id + 1
}
//使用系统前输入密码 超过3次则退出系统
func Auth() bool {
	//password, err := os.Open(passwordFile)
	password ,err := ioutil.ReadFile(passwordFile)
	//打开密码文件如果err!=nil 就是说打开有问题
	if err != nil || len(password) < 1 {
		//如果是因为不存在 那么我们需要初始化密码
		if os.IsNotExist(err) || len(password) < 1 {
			fmt.Print("请输入初始化密码:")
			bytes, _ := gopass.GetPasswd()
			//将用户输入的密码md5加密  写入文件
			ioutil.WriteFile(passwordFile, []byte(fmt.Sprintf("%x",md5.Sum(bytes))), 0644)
			return true
		} else { //如果不是因为不存在  那么打印报错信息
			fmt.Println(err)
		}
	} else { //如果存在 那么就需要做密码验证
		//defer  password.Close()
		for i := 1; i <= maxauth; i++ {
			// user := Inputstring("请输入密码:")
			fmt.Printf("请输入密码:")
			bytes, _ := gopass.GetPasswd()
			//这里对输入的密码进行md5加密并且与常量比较
			//%x是小写十六进制表示 Sprintf格式化返回一个字符串
			passwd ,_:= ioutil.ReadFile(passwordFile)
			if fmt.Sprintf("%x", md5.Sum(bytes)) == string(passwd) {
				return true
			} else {
				fmt.Printf("输入错误请重新输入,您还有%d次机会\n", maxauth-i)
			}
		}
		return false
	}
	return false
}


func SetPassword() {
	fmt.Printf("请输入旧密码:")
	bytes, _ := gopass.GetPasswd()
	if passwd ,_:= ioutil.ReadFile(passwordFile);string(passwd) == fmt.Sprintf("%x",md5.Sum(bytes)){
		fmt.Print("请输入新密码")
		bytes, _ := gopass.GetPasswd()
		ioutil.WriteFile(passwordFile, []byte(fmt.Sprintf("%x",md5.Sum(bytes))), 0644)
		fmt.Println("密码修改成功")
	}else {
		fmt.Println("密码输入错误")
	}
}
//add.go
package lib

import "fmt"

//添加用户
func Add(id int) {
	Inputuser(id)
	fmt.Println("[+]添加成功")
}
//修改用户
//change.go
package lib

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

func Change() {
	UserInfo := Persi.LoadUser()
	if id, err := strconv.Atoi(Inputstring("请输入修改的用户id:")); err == nil {
		fmt.Println(strings.Repeat("-", 20))
		if user, ok := UserInfo[id]; ok {
			fmt.Printf("ID:%d\nname:%s\nbirthday:%v\ntel:%s\naddr:%s\ndesc:%s\n",user.ID, user.Name,user.Birthday.Format("2006-1-2"),user.Tel,user.Addr,user.Desc)
			fmt.Println(strings.Repeat("-", 20))
			affirm := Inputstring("确认是否修改(Y/N):")
			if affirm == "Y" || affirm == "y" {
				Inputuser(id)
			}
		} else {
			fmt.Println("用户id不存在")
		}
	} else {
		fmt.Println("输入错误")
	}
}
//查询用户
//sel.go
package lib

import (
	"fmt"
	"sort"
	"strings"
)

func Sel() {
	UserInfo := Persi.LoadUser()
	user := Inputstring("请输入要查询的信息:")
	list := make([]User,0)
	fmt.Println(strings.Repeat("-", 20))
	for _, v := range UserInfo {
		if strings.Contains(v.Name, user) || strings.Contains(v.Desc, user) || strings.Contains(v.Addr, user) || strings.Contains(v.Tel, user) || strings.Contains(v.Birthday.Format("2006-01-02"), user)  {
			list = append(list,v)
		}
	}
	users := Inputstring("请输入要排序的属性(ID,Name,Desc,Addr,Tel,Birthday):")
	sort.Slice(list, func(i, j int) bool {
		switch users {
		case "ID":
			return  list[i].ID < list[j].ID
		case "Name":
			return  list[i].Name < list[j].Name
		case "Desc":
			return  list[i].Desc < list[j].Desc
		case "Addr":
			return  list[i].Addr < list[j].Addr
		case "Tel":
			return  list[i].Tel < list[j].Tel
		case "Birthday":
			return  list[i].Birthday.Format("2006-1-2") < list[j].Birthday.Format("2006-1-2")
		default:
			return list[i].ID < list[j].ID
		}
	})
	for _,v := range  list {
		fmt.Printf("ID:%d\nname:%s\nbirthday:%v\ntel:%s\naddr:%s\ndesc:%s\n", v.ID,v.Name,v.Birthday.Format("2006-1-2"),v.Tel,v.Addr,v.Desc)
		fmt.Println(strings.Repeat("-", 20))
	}


}
//删除用户
//del.go
package lib

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

func Del() {
	UserInfo := Persi.LoadUser()
	if id, err := strconv.Atoi(Inputstring("请输入删除的用户id:")); err == nil {
		fmt.Println(strings.Repeat("-", 20))
		if user, ok := UserInfo[id]; ok {
			fmt.Printf("ID:%d\nname:%s\nbirthday:%v\ntel:%s\naddr:%s\ndesc:%s\n",user.ID ,user.Name,user.Birthday.Format("2006-1-2"),user.Tel,user.Addr,user.Desc)
			fmt.Println(strings.Repeat("-", 20))
			affirm := Inputstring("确认是否删除(Y/N):")
			if affirm == "Y" || affirm == "y" {
				delete(UserInfo, id)
				Persi.SaveUser(UserInfo)
				fmt.Println("[-]删除成功")
			}
		} else {
			fmt.Println("用户id不存在")
		}
	} else {
		fmt.Println("输入错误")
	}
}
相关标签: GO语言编程