php小編子墨在使用Go語言開發(fā)過程中,可能會(huì)遇到一個(gè)常見的錯(cuò)誤:“Go錯(cuò)誤:time.Time未實(shí)現(xiàn)driver.Valuer(缺少方法Value)”。這個(gè)錯(cuò)誤通常在將time.Time類型的值存儲(chǔ)到數(shù)據(jù)庫(kù)中時(shí)出現(xiàn)。它表明time.Time類型沒有實(shí)現(xiàn)driver.Valuer接口,并且缺少Value方法。解決這個(gè)問題的方法有很多,我們可以通過自定義一個(gè)新的時(shí)間類型,或者使用第三方庫(kù)來處理時(shí)間類型的存儲(chǔ)。在本文中,我們將詳細(xì)介紹這個(gè)錯(cuò)誤的原因和解決方案,幫助開發(fā)者更好地理解和解決這個(gè)問題。
問題內(nèi)容
我正在開發(fā)一個(gè) Go 項(xiàng)目,在該項(xiàng)目中,我使用 sqlboiler 從我使用 setup.sh 腳本創(chuàng)建的 SQLite3 數(shù)據(jù)庫(kù)生成代碼。我遇到了一個(gè)似乎無法解決的錯(cuò)誤。錯(cuò)誤信息是:
graph/db/repositories.go:998:23: cannot use o.CreatedAt (variable of type string) as driver.Valuer value in argument to queries.MustTime: string does not implement driver.Valuer (missing method Value) graph/db/repositories.go:999:23: cannot use &o.CreatedAt (value of type *string) as sql.Scanner value in argument to queries.SetScanner: *string does not implement sql.Scanner (missing method Scan)
登錄后復(fù)制
當(dāng)我嘗試在 graph/db/repositories.go 文件中使用 time.Time 值時(shí),會(huì)發(fā)生此錯(cuò)誤。我正在為我的項(xiàng)目使用 golang:1.21-alpine3.18 Docker 映像。
我嘗試更改 SQLite3 數(shù)據(jù)庫(kù)的存儲(chǔ)庫(kù)表中的created_at 列類型。我已經(jīng)使用 TEXT 和 TIMESTAMP 數(shù)據(jù)類型對(duì)其進(jìn)行了測(cè)試,但錯(cuò)誤仍然存??在。
有誰知道可能導(dǎo)致此錯(cuò)誤的原因以及如何解決它?
repositories.go
func (o *Repository) Insert(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) error { if o == nil { return errors.New("db: no repositories provided for insertion") } var err error if !boil.TimestampsAreSkipped(ctx) { currTime := time.Now().In(boil.GetLocation()) if queries.MustTime(o.CreatedAt).IsZero() { queries.SetScanner(&o.CreatedAt, currTime) } } if err := o.doBeforeInsertHooks(ctx, exec); err != nil { return err } nzDefaults := queries.NonZeroDefaultSet(repositoryColumnsWithDefault, o) key := makeCacheKey(columns, nzDefaults) repositoryInsertCacheMut.RLock() cache, cached := repositoryInsertCache[key] repositoryInsertCacheMut.RUnlock()
登錄后復(fù)制
setup.sh
#!/usr/local/bin/sh set -eu readonly DBFILE_NAME="mygraphql.db" # Create DB file if [ ! -e ${DBFILE_NAME} ];then echo ".open ${DBFILE_NAME}" | sqlite3 fi # Create DB Tables echo "creating tables..." sqlite3 ${DBFILE_NAME} " PRAGMA foreign_keys = ON; CREATE TABLE IF NOT EXISTS users(\ id TEXT PRIMARY KEY NOT NULL,\ name TEXT NOT NULL,\ project_v2 TEXT\ ); CREATE TABLE IF NOT EXISTS repositories(\ id TEXT PRIMARY KEY NOT NULL,\ owner TEXT NOT NULL,\ name TEXT NOT NULL,\ created_at TEXT NOT NULL DEFAULT (DATETIME('now','localtime')),\ FOREIGN KEY (owner) REFERENCES users(id)\ ); CREATE TABLE IF NOT EXISTS issues(\ id TEXT PRIMARY KEY NOT NULL,\ url TEXT NOT NULL,\ title TEXT NOT NULL,\ closed INTEGER NOT NULL DEFAULT 0,\ number INTEGER NOT NULL,\ repository TEXT NOT NULL,\ CHECK (closed IN (0, 1)),\ FOREIGN KEY (repository) REFERENCES repositories(id)\ ); CREATE TABLE IF NOT EXISTS projects(\ id TEXT PRIMARY KEY NOT NULL,\ title TEXT NOT NULL,\ url TEXT NOT NULL,\ owner TEXT NOT NULL,\ FOREIGN KEY (owner) REFERENCES users(id)\ ); CREATE TABLE IF NOT EXISTS pullrequests(\ id TEXT PRIMARY KEY NOT NULL,\ base_ref_name TEXT NOT NULL,\ closed INTEGER NOT NULL DEFAULT 0,\ head_ref_name TEXT NOT NULL,\ url TEXT NOT NULL,\ number INTEGER NOT NULL,\ repository TEXT NOT NULL,\ CHECK (closed IN (0, 1)),\ FOREIGN KEY (repository) REFERENCES repositories(id)\ ); CREATE TABLE IF NOT EXISTS projectcards(\ id TEXT PRIMARY KEY NOT NULL,\ project TEXT NOT NULL,\ issue TEXT,\ pullrequest TEXT,\ FOREIGN KEY (project) REFERENCES projects(id),\ FOREIGN KEY (issue) REFERENCES issues(id),\ FOREIGN KEY (pullrequest) REFERENCES pullrequests(id),\ CHECK (issue IS NOT NULL OR pullrequest IS NOT NULL)\ ); " # Insert initial data echo "inserting initial data..." sqlite3 ${DBFILE_NAME} " PRAGMA foreign_keys = ON; INSERT INTO users(id, name) VALUES\ ('U_1', 'hsaki') ; INSERT INTO repositories(id, owner, name) VALUES\ ('REPO_1', 'U_1', 'repo1') ; INSERT INTO issues(id, url, title, closed, number, repository) VALUES\ ('ISSUE_1', 'http://example.com/repo1/issue/1', 'First Issue', 1, 1, 'REPO_1'),\ ('ISSUE_2', 'http://example.com/repo1/issue/2', 'Second Issue', 0, 2, 'REPO_1'),\ ('ISSUE_3', 'http://example.com/repo1/issue/3', 'Third Issue', 0, 3, 'REPO_1')\ ; INSERT INTO projects(id, title, url, owner) VALUES\ ('PJ_1', 'My Project', 'http://example.com/project/1', 'U_1')\ ; INSERT INTO pullrequests(id, base_ref_name, closed, head_ref_name, url, number, repository) VALUES\ ('PR_1', 'main', 1, 'feature/kinou1', 'http://example.com/repo1/pr/1', 1, 'REPO_1'),\ ('PR_2', 'main', 0, 'feature/kinou2', 'http://example.com/repo1/pr/2', 2, 'REPO_1')\ ; "
登錄后復(fù)制
sqlboiler.toml
pkgname="db" output="graph/db" wipe=true add-global-variants=false no-tests=true [sqlite3] dbname = "./mygraphql.db"
登錄后復(fù)制
環(huán)境
? MacBook Pro M1 Pro
登錄后復(fù)制
解決方法
我會(huì)說更新 Go 中的存儲(chǔ)庫(kù)結(jié)構(gòu),將 CreatedAt 作為 time.Time 字段。
將值分配給 CreatedAt 時(shí),請(qǐng)使用 time.Time 值。例如, currTime := time.Now()
讓你的結(jié)構(gòu)像這樣
type Repository struct { ID string `boil:"id" json:"id" toml:"id" yaml:"id"` Owner string `boil:"owner" json:"owner" toml:"owner" yaml:"owner"` Name string `boil:"name" json:"name" toml:"name" yaml:"name"` CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` // other fields... }
登錄后復(fù)制
然后設(shè)置 CreatedAt 值:
repository := &Repository{ ID: "some-id", Owner: "owner-id", Name: "repo-name", CreatedAt: time.Now(), // setting it as time.Time }
登錄后復(fù)制