package user import ( "context" "database/sql" "errors" "strings" "time" ) var ErrUserAlreadyExists = errors.New("user already exists") type User struct { ID int64 Username string PasswordHash string CreatedAt time.Time } type UserRepo struct { db *sql.DB } func NewUserRepo(db *sql.DB) *UserRepo { return &UserRepo{db: db} } func (r *UserRepo) Create(ctx context.Context, username string, passwordHash string) error { // sqlite 不同版本/驱动对 unique 冲突错误信息不完全一致,用字符串兜底识别。 _, err := r.db.ExecContext(ctx, `INSERT INTO users(username, password_hash) VALUES(?, ?)`, username, passwordHash, ) if err != nil { msg := strings.ToLower(err.Error()) if strings.Contains(msg, "unique") || strings.Contains(msg, "constraint failed") { return ErrUserAlreadyExists } return err } return nil } func (r *UserRepo) GetByUsername(ctx context.Context, username string) (*User, error) { var u User row := r.db.QueryRowContext(ctx, `SELECT id, username, password_hash, created_at FROM users WHERE username = ?`, username, ) if err := row.Scan(&u.ID, &u.Username, &u.PasswordHash, &u.CreatedAt); err != nil { return nil, err } return &u, nil }