igozhang

——

    go_mysql

    https://go.dev/doc/tutorial/database-access
    go version go1.19.5 linux/amd64
    CentOS Linux release 7.6.1810 (Core)
    
    初始化mysql5.7容器
    编写代码
    编译运行
    错误处理
    
    cd /go
    mkdir data-access
    cd data-access
    go mod init example/data-access
    
    初始化mysql5.7容器
    # docker run -itd --name mysql57-igo -p3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
    https://igozhang.cn/dbclient_ins
    
    初始化4条数据:
    mysql> create database recordings;
    mysql> use recordings;
    
    DROP TABLE IF EXISTS album;
    CREATE TABLE album (
      id         INT AUTO_INCREMENT NOT NULL,
      title      VARCHAR(128) NOT NULL,
      artist     VARCHAR(255) NOT NULL,
      price      DECIMAL(5,2) NOT NULL,
      PRIMARY KEY (`id`)
    );
    INSERT INTO album
      (title, artist, price)
    VALUES
      ('Blue Train', 'John Coltrane', 56.99),
      ('Giant Steps', 'John Coltrane', 63.99),
      ('Jeru', 'Gerry Mulligan', 17.99),
      ('Sarah Vaughan', 'Sarah Vaughan', 34.98);
    
    mysql> select * from album;
    grant all privileges on recordings.* to igo_rw@"%" identified by 'mi';
    
    编写代码main.go
    
    package main
    
    import (
        "database/sql"
        "fmt"
        "log"
        "os"
    
        "github.com/go-sql-driver/mysql"
    )
    var db *sql.DB
    type Album struct {
        ID     int64
        Title  string
        Artist string
        Price  float32
    }
    
    func main() {
        // Capture connection properties.
        cfg := mysql.Config{
            User:   os.Getenv("DBUSER"),
            Passwd: os.Getenv("DBPASS"),
            Net:    "tcp",
            Addr:   "127.0.0.1:3306",
            DBName: "recordings",
            AllowNativePasswords: true, //规避报错1
        }
        // Get a database handle.
        var err error
        db, err = sql.Open("mysql", cfg.FormatDSN())
        if err != nil {
            log.Fatal(err)
        }
    
        pingErr := db.Ping()
        if pingErr != nil {
            log.Fatal(pingErr)
        }
        fmt.Println("Connected!")
    
        albums, err := albumsByArtist("John Coltrane")
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("Albums found: %v\n", albums)
    
        // Hard-code ID 2 here to test the query.
        alb, err := albumByID(2)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("Album found: %v\n", alb)
    
    albID, err := addAlbum(Album{
        Title:  "The Modern Sound of Betty Carter",
        Artist: "Betty Carter",
        Price:  49.99,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("ID of added album: %v\n", albID)
    
    }
    
    // albumsByArtist queries for albums that have the specified artist name.
    func albumsByArtist(name string) ([]Album, error) {
        // An albums slice to hold data from returned rows.
        var albums []Album
    
        rows, err := db.Query("SELECT * FROM album WHERE artist = ?", name)
        if err != nil {
            return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
        }
        defer rows.Close()
        // Loop through rows, using Scan to assign column data to struct fields.
        for rows.Next() {
            var alb Album
            if err := rows.Scan(&alb.ID, &alb.Title, &alb.Artist, &alb.Price); err != nil {
                return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
            }
            albums = append(albums, alb)
        }
        if err := rows.Err(); err != nil {
            return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
        }
        return albums, nil
    }
    
    // albumByID queries for the album with the specified ID.
    func albumByID(id int64) (Album, error) {
        // An album to hold data from the returned row.
        var alb Album
    
        row := db.QueryRow("SELECT * FROM album WHERE id = ?", id)
        if err := row.Scan(&alb.ID, &alb.Title, &alb.Artist, &alb.Price); err != nil {
            if err == sql.ErrNoRows {
                return alb, fmt.Errorf("albumsById %d: no such album", id)
            }
            return alb, fmt.Errorf("albumsById %d: %v", id, err)
        }
        return alb, nil
    }
    
    // addAlbum adds the specified album to the database,
    // returning the album ID of the new entry
    func addAlbum(alb Album) (int64, error) {
        result, err := db.Exec("INSERT INTO album (title, artist, price) VALUES (?, ?, ?)", alb.Title, alb.Artist, alb.Price)
        if err != nil {
            return 0, fmt.Errorf("addAlbum: %v", err)
        }
        id, err := result.LastInsertId()
        if err != nil {
            return 0, fmt.Errorf("addAlbum: %v", err)
        }
        return id, nil
    }
    
    编译运行
    # go get .
    # export DBUSER=root
    # export DBPASS=123456
    # go run .
    Connected!
    Albums found: [{1 Blue Train John Coltrane 56.99} {2 Giant Steps John Coltrane 63.99}]
    Album found: {2 Giant Steps John Coltrane 63.99}
    ID of added album: 5
    
    错误处理
    报错1
    # go run .
    [mysql] 2023/02/02 11:54:42 connector.go:95: could not use requested auth plugin 'mysql_native_password': this user requires mysql native password authentication.
    2023/02/02 11:54:42 this user requires mysql native password authentication.
    exit status 1
    
    解决
            AllowNativePasswords: true, //规避报错1
    

    MP3