go练习实现通讯录client

94 阅读4分钟

实现一个 通讯录管理系统,可以设计一个简单的命令行应用(CLI),主要功能包括联系人信息的存储、查询、修改和删除。以下功能说明:

1. 添加联系人

  • 用户可以添加新联系人,包括姓名、电话、电子邮件、地址信息。
  • 校验输入的信息(如电话格式、电子邮件格式等)是否有效。

2. 查看联系人

  • 用户可以查看所有联系人信息。

3. 修改联系人

  • 用户可以根据姓名标识查找联系人,修改其信息(如电话、地址、邮箱等)。
  • 确保修改后的数据有效。

4. 删除联系人

  • 用户可以删除联系人(通过姓名标识删除)。

5. 数据持久化

  • 使用文件存储联系人信息,确保退出程序后数据能够保留。
  • 可以使用 JSON格式存储联系人数据。
package main

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
)

type Contact struct {
	Phone   string
	Email   string
	Address string
}

var addressBook = make(map[string]Contact)

func showMenu() {
	fmt.Println("欢迎使用通讯录管理系统")
	fmt.Println("0. 显示通讯录")
	fmt.Println("1. 添加联系人")
	fmt.Println("2. 删除联系人")
	fmt.Println("3. 查找联系人")
	fmt.Println("4. 修改联系人")
	fmt.Println("5. 退出程序")
}

func modifyContact(addressBook map[string]Contact, name string) error {
	fmt.Println("请继续输入联系人信息:")
	fmt.Print("电话: ")
	var phone string
	for {
		fmt.Scanln(&phone)
		if err := isValidPhone(phone); err != nil {
			fmt.Println("电话号码格式有问题,请重新输入电话号码,或者退出修改")
			fmt.Println("1. 重新输入电话号码")
			fmt.Println("2. 退出修改")
			var choice int
			fmt.Scanln(&choice)
			if choice == 1 {
				fmt.Println("请重新输入电话号码")
				continue
			} else if choice == 2 {
				return fmt.Errorf("通讯录无变化")
			}
		} else {
			break
		}
	}

	// 验证邮箱是否合法
	// 邮箱可以为空
	fmt.Println("邮箱可以为空,直接回车")
	fmt.Print("邮箱: ")
	var email string
	for {
		fmt.Scanln(&email)
		if email != "" {
			if err := isValidEmail(email); err != nil {
				// 提示用户邮箱格式有问题,请重新输入邮箱,或者退出修改
				fmt.Println("邮箱格式有问题,请重新输入邮箱,或者退出修改")
				fmt.Println("1. 重新输入邮箱")
				fmt.Println("2. 退出修改")
				var choice int
				fmt.Scanln(&choice)
				if choice == 1 {
					fmt.Println("请重新输入邮箱")
					continue
				} else if choice == 2 {
					return fmt.Errorf("通讯录无变化")
				}
			} else {
				break
			}
		} else {
			break
		}
	}

	// 验证地址是否合法
	fmt.Println("地址可以为空,直接回车")
	fmt.Print("地址: ")
	var address string
	for {
		fmt.Scanln(&address)
		if address != "" {
			if err := isValidAddress(address); err != nil {
				// 提示用户地址格式有问题,请重新输入地址,或者退出修改
				fmt.Println("地址格式有问题,请重新输入地址,或者退出修改")
				fmt.Println("1. 重新输入地址")
				fmt.Println("2. 退出修改")
				var choice int
				fmt.Scanln(&choice)
				if choice == 1 {
					fmt.Println("请重新输入地址")
					continue
				} else if choice == 2 {
					return fmt.Errorf("通讯录无变化")
				}
			} else {
				break
			}
		} else {
			break
		}
	}
	// 添加联系人
	addressBook[name] = Contact{
		Phone:   phone,
		Email:   email,
		Address: address,
	}
	return nil
}

func addAddressBook(addressBook map[string]Contact) {
	fmt.Println("请输入联系人信息:")
	fmt.Print("姓名: ")
	var name string
	fmt.Scanln(&name)
	if _, ok := addressBook[name]; ok {
		fmt.Println("联系人已存在")
		return
	}
	err := modifyContact(addressBook, name)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("联系人添加成功")
	saveAddressBook(addressBook)
}

func deleteAddressBook(addressBook map[string]Contact) {
	fmt.Println("请输入要删除的联系人姓名:")
	var name string
	fmt.Scanln(&name)
	if _, ok := addressBook[name]; !ok {
		fmt.Println("联系人不存在")
		return
	}
	delete(addressBook, name)
	fmt.Println("联系人删除成功")
	saveAddressBook(addressBook)
}

func searchAddressBook(addressBook map[string]Contact) {
	fmt.Println("请输入要查找的联系人姓名:")
	var name string
	fmt.Scanln(&name)
	if _, ok := addressBook[name]; !ok {
		fmt.Println("联系人不存在")
		return
	}
	fmt.Printf("联系人信息: %+v\n", addressBook[name])
}

func modifyAddressBook(addressBook map[string]Contact) {
	fmt.Println("请输入要修改的联系人姓名:")
	var name string
	fmt.Scanln(&name)
	if _, ok := addressBook[name]; !ok {
		fmt.Println("联系人不存在")
		return
	}
	err := modifyContact(addressBook, name)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("联系人修改成功")
	saveAddressBook(addressBook)
}

func isValidPhone(phone string) error {
	if len(phone) != 11 {
		return fmt.Errorf("电话号码长度不合法")
	}
	// 验证电话号码是否为数字
	for _, char := range phone {
		if char < '0' || char > '9' {
			return fmt.Errorf("电话号码不合法")
		}
	}
	return nil
}

func isValidEmail(email string) error {
	if !strings.Contains(email, "@") {
		return fmt.Errorf("邮箱不合法")
	}
	return nil
}

func isValidAddress(address string) error {
	if len(address) < 10 {
		return fmt.Errorf("地址长度不合法")
	}
	return nil
}

func showAddressBook(addressBook map[string]Contact) {
	fmt.Println("通讯录:")
	fmt.Println("--------------------------------")
	fmt.Println("姓名\t电话\t邮箱\t地址")
	fmt.Println("--------------------------------")
	for name, contact := range addressBook {
		fmt.Printf("%s\t%s\t%s\t%s\n", name, contact.Phone, contact.Email, contact.Address)
	}
	fmt.Println("--------------------------------")
}

func saveAddressBook(addressBook map[string]Contact) {
	data, err := json.Marshal(addressBook)
	if err != nil {
		fmt.Println("保存通讯录失败:", err)
		return
	}
	err = os.WriteFile("addressBook.json", data, 0644)
	if err != nil {
		fmt.Println("保存通讯录失败:", err)
		return
	}
}

func loadAddressBook(addressBook map[string]Contact) {
	data, err := os.ReadFile("addressBook.json")
	if err != nil {
		fmt.Println("读取通讯录失败")
		return
	}
	json.Unmarshal(data, &addressBook)
}

func initAddressBook() {
	//判断是否存在文件,如果不存在创建通讯录文件
	if _, err := os.Stat("addressBook.json"); os.IsNotExist(err) {
		os.Create("addressBook.json")
	}
}

func main() {
	initAddressBook()
	loadAddressBook(addressBook)
	for {
		showMenu()
		var choice int
		fmt.Scanln(&choice)
		switch choice {
		case 0:
			showAddressBook(addressBook)
		case 1:
			addAddressBook(addressBook)
		case 2:
			deleteAddressBook(addressBook)
		case 3:
			searchAddressBook(addressBook)
		case 4:
			modifyAddressBook(addressBook)
		case 5:
			fmt.Println("退出程序")
			return
		default:
			fmt.Println("输入错误")
		}
	}
}