go入门项目:(1) 基于命令行的图书的增删查改

Go 语言入门练手项目系列

本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/gobeginner-proj-bookstore-cli.html

介绍

这是一个基于go应用程序命令行的bookstore小项目,具体实现了图书的增删改查,适合刚入门go的朋友熟悉go的语法。

知识点

  • go flag,提供了命令行参数解析的功能
  • go json的序列化与反序列化
  • go ioutil 读写文件

功能演示

  1. 列出全部图书
$ .\bookstore.exe get -all
Id      Title                   Author
1       Go语言圣经              Ailen A
2       Java编程思想            Bruce Eckel
3       流畅的Python            Luciano Ramalho
4       PHP权威指南             CENJW
  1. 通过id获取相应图书
$ .\bookstore.exe get -id 1
Id      Title           Author
1       Go语言圣经      Ailen A
  1. 添加图书
$ .\bookstore.exe add -id 123 -title 'Head First Go' -author unknown
add successfully!

  1. 添加图书,如果已经存在相同id的图书,提示已存在
$ .\bookstore.exe add -id 1 -title test -author test
2022/06/24 18:05:44 Book already exists.

  1. 更新图书
$ .\bookstore.exe update -id 123 -title 'head first go' -author UNKNOWN
update successfully!

  1. 删除图书
$ .\bookstore.exe delete -id 123
Delete successfully!

本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/gobeginner-proj-bookstore-cli.html

功能实现

main.go

func main() {
    // get book/books
    getCmd := flag.NewFlagSet("get", flag.ExitOnError)
    getAll := getCmd.Bool("all", false, "List all books")
    getId := getCmd.String("id", "", "Get a book by id")

    // add/update book
    addCmd := flag.NewFlagSet("add", flag.ExitOnError)
    addId := addCmd.String("id", "", "Book id")
    addTitle := addCmd.String("title", "", "Book title")
    addAuthor := addCmd.String("author", "", "Book author")

    // delete book
    deleteCmd := flag.NewFlagSet("delete", flag.ExitOnError)
    deleteId := deleteCmd.String("id", "", "Book id")

    // check command
    if len(os.Args) < 2 {
        log.Fatal("Expected get, add, update, delete commands.")
    }

    switch os.Args[1] {
    case "get":
        handleGetBooks(getCmd, getAll, getId)
    case "add":
        handleAddOrUpdateBook(addCmd, addId, addTitle, addAuthor, true)
    case "update":
        handleAddOrUpdateBook(addCmd, addId, addTitle, addAuthor, false)
    case "delete":
        handleDeleteBook(deleteCmd, deleteId)
    default:
        fmt.Println("Pls provide get, add, update, delete commands.")
    }

}

books.go

type Book struct {
    Id     string json:"id"
    Title  string json:"title"
    Author string json:"author"
}

// get all the books logic
func handleGetBooks(getCmd *flag.FlagSet, all *bool, id *string) {
    getCmd.Parse(os.Args[2:])

    if !*all && *id == "" {
        fmt.Println("subcommand --all or --id needed") // PrintDefault打印集合中所有注册好的flag的默认值。除非另外配置,默认输出到标准错误输出中。
        getCmd.PrintDefaults()
        os.Exit(1)
    }

    if *all {
        books := getBooks()
        fmt.Println("Id\tTitle\t\t\tAuthor\t")
        for _, book := range books {
            fmt.Printf("%v\t%v\t\t%v\t\n", book.Id, book.Title, book.Author)
        }
    }

    if *id != "" {
        var isExist bool
        books := getBooks()
        fmt.Println("Id\tTitle\t\tAuthor\t")
        for _, book := range books {
            if book.Id == *id {
                fmt.Printf("%v\t%v\t%v\t\n", book.Id, book.Title, book.Author)
                isExist = true
            }
        }

        if !isExist {
            log.Fatal("Book not found!")
        }
    }
}

// add or update a book logic
// addBook: true denote add a new book to file, false denote update a book
func handleAddOrUpdateBook(addCmd *flag.FlagSet, id, title, author *string, addBook bool) {
    addCmd.Parse(os.Args[2:])

    if *id == "" || *title == "" || *author == "" {
        addCmd.PrintDefaults()
        log.Fatal("Pls provide id, title, author commands.")
    }
    books := getBooks()
    var newBook Book
    if addBook {
        for _, book := range books {
            if book.Id == *id {
                log.Fatal("Book already exists.")
            } else {
                newBook = Book{*id, *title, *author}
                books = append(books, newBook)
                break
            }
        }

    } else {
        var isExist bool
        for i, book := range books {
            if book.Id == *id {
                books[i] = Book{Id: *id, Title: *title, Author: *author}
                isExist = true
            }
        }

        err := saveBooks(books)
        checkError(err)

        if !isExist {
            log.Fatal("Book not found")
        }

    }

    saveBooks(books)

    fmt.Printf("%s successfully!\n", os.Args[1])
}

func handleDeleteBook(deleteCmd *flag.FlagSet, id *string) {
    deleteCmd.Parse(os.Args[2:])

    if *id == "" {
        deleteCmd.PrintDefaults()
        log.Fatal("Pls provide id command.")
    }

    if *id != "" {
        var isExist bool
        books := getBooks()
        for i, book := range books {
            if book.Id == *id {
                books = append(books[:i], books[i+1:]...)
                isExist = true
            }
        }

        if !isExist {
            log.Fatal("Book not found!")
        }

        err := saveBooks(books)
        checkError(err)

        fmt.Println("Delete successfully!")
    }
}

func saveBooks(books []Book) error {
    bookBytes, err := json.Marshal(books)
    checkError(err)
    err = ioutil.WriteFile("./books.json", bookBytes, 0644)
    return err
}

func getBooks() (books []Book) {
    bookBytes, err := ioutil.ReadFile("./books.json")
    checkError(err)
    err = json.Unmarshal(bookBytes, &books)
    checkError(err)
    return books
}

func checkError(err error) {
    if err != nil {
        log.Fatal("Error happended ", err)
    }
}

Original: https://www.cnblogs.com/cenjw/p/gobeginner-proj-bookstore-cli.html
Author: jvvcen
Title: go入门项目:(1) 基于命令行的图书的增删查改

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/516273/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Excelize 发布 2.6.0 版本,功能强大的 Excel 文档基础库

    Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Mic…

    Go语言 2023年5月25日
    079
  • Golang WaitGroup源码解析

    Go WaitGroup源码解析 结构体 type WaitGroup struct { noCopy noCopy state1 [3]uint32 } 其中state1代表三个…

    Go语言 2023年5月25日
    082
  • Goland的那些实用技巧

    1、 自定义结构体tag 2、go mod tidy / download失败 解决办法:设置goproxy 3、取消/打开代码折叠 4、左侧project栏总是展示当前打开文件的…

    Go语言 2023年5月25日
    071
  • golang的defer踩坑汇总

    变量捕获 defer中的变量会被提前捕获,后续的修改不会影响到已捕获的值,举个例子: 结果defer语句中打印的值是修改前的值。: 最后输出值: 10 Defer运行值: 0 变量…

    Go语言 2023年5月25日
    051
  • go tool – 快速生成CHANGELOG.md

    在git项目中,通过添加CHANGELOG.md可以展示项目的版本更新记录,方便用户查看项目的重大bug修复或不兼容版本信息。 安装: 打开项目目录运行 或者通过命令行指定项目目录…

    Go语言 2023年5月25日
    062
  • sqlx操作MySQL实战及其ORM原理

    sqlx是Golang中的一个知名三方库,其为Go标准库database/sql提供了一组扩展支持。使用它可以方便的在数据行与Golang的结构体、映射和切片之间进行转换,从这个角…

    Go语言 2023年5月25日
    067
  • Maglev : A Fast and Reliable Software Network Load Balancer (using Consistent Hashing)

    前言(为什么想读这一篇论文) 这一篇论文吸引我注意的原因是,Consistent Hashing ;本来的特性就是作为分布式缓存之用。谷歌将他们的负载均衡器(代号:Maglev)发…

    Go语言 2023年5月25日
    056
  • Go代码规范梳理

    注释语句 // Request 表示运行命令的请求。 type Request struct { … // Encode 将 req 的 JSON 编码写入 w 。 func …

    Go语言 2023年5月25日
    066
  • go语言 函数return值的几种情况

    分三种情况 (以下 “指定返回值”这句话, 仅指return后面直接跟着的返回值) 退出执行,不指定返回值 *(1) 函数没有返回值 package mai…

    Go语言 2023年5月29日
    071
  • Go语言之Goroutine与信道、异常处理

    一、Goroutine Go 协程可以看做成一个轻量级的线程,Go 协程相比于线程的优势: Goroutine 的成本更低大小只有 2 kb 左右,线程有几个兆。 Goroutin…

    Go语言 2023年5月25日
    057
  • 雅可比行列式迭代及优化(golang版)

    最近遇到的一个求解雅可比迭代的问题,这个计算方法在 python 中有现成的库,但是在 golang 中没找到相应的实现。于是根据雅可比行列式的推导实现了一个 golang 版本的…

    Go语言 2023年5月25日
    059
  • golang tcp keepalive研究记录(基于websocket)

    服务器和客户端建立tcp连接以后,客户端/服务器如何知道对方是否挂掉了? 这时候TCP协议提出一个办法,当客户端端等待超过一定时间后自动给服务端发送一个空的报文,如果对方回复了这个…

    Go语言 2023年5月25日
    046
  • go泛型教程

    导读: 约束 使用方法 实现原理 跟其它语言的泛型进行对比 用例子学泛型 issues 泛型需满足 go1.18+ go使用interface作为约束,约束的意思是约束了这个泛型都…

    Go语言 2023年5月25日
    053
  • 编译kubeadm使生成证书有效期为100年

    问题 编译 检查结果 问题 当我使用kubeadm部署成功k8s集群时在想默认生成的证书有效期是多久,如下所示 /etc/kubernetes/pki/apiserver.crt …

    Go语言 2023年5月25日
    052
  • 自己实现一个Controller——精简型

    写在最前 controller-manager作为K8S master的其中一个组件,负责众多controller的启动和终止,这些controller负责监控着k8s中各种资源,…

    Go语言 2023年5月25日
    052
  • go实用编程-算法篇 -归并排序

    /**** // i: the begin index of old sub-array, j: the begin index of even sub-array | array…

    Go语言 2023年5月25日
    070
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球