2014-01-16 1 views
8

データベースで作業している場合は、通常は「ゼロ」値を通過させたくない場合、NOT NULL制約などをキックしたい場合が多いため、ほとんどのシナリオではNull*タイプが便利です必要なすべてのデータを渡していないことを伝えます。ゴールンはNull *型で効果的に動作します

ですから、次のような構造を作成:偉大

type Role struct { 
    Id sql.NullInt64 
    Code sql.NullString 
} 

ザッツを、今あなたがプロパティに直接アクセスを取得し、取得し、セットの両方にRole.Id.Valueを使用することはできません、これはかなり取得する予定ですあなたがプロパティにアクセスするたびに余分な手順を取らなければならないときは、大きなアプリで古いものです。

直接割り当てることができればいいですね。 Role.Code = "Fsfs"となり、ヌルチェックに興味があるときはRole.Code.IsNullのようなことができます。そんなことは可能ですか?

+0

ポインタの扱いに問題がなければ、ポインタは0の値を持ちます - 'type Role struct {Code * string}' – codepushr

答えて

1

中間ポインタ値を使用していますか?

package main 

import "fmt" 

type tmp struct { 
    Value int 
} 

func getInt() *int { 
    i := 123 

    return &i 
} 

func main() { 
    // Re 
    var v *int 

    v = nil 

    fmt.Printf("%T/%v\n", v, v) 

    if v == nil { 
     println("nil...") 
    } 

    v = getInt() 

    fmt.Printf("%T/%v\n", v, *v) 

    if v != nil { 
     println("not nil...") 
    } 

    s := tmp{*v} 

    fmt.Printf("%T/%v\n", s, s) 
} 

http://play.golang.org/p/lBrwTKh6-v

1

あなたはそのようRole.Codeにアクセスすることができます。

var r *Role 
r.Code = *code 

あなたはこのようにnullをチェックすることができます:あなたはrの値を変更した場合

fmt.Println(r.Code, r.Code.Valid) 

.Codeを手動でsql.Scannerを使用せずに設定すると便利です:

func (r *Role) SetCode(code string) { 
    r.Code.String = code 
    r.Code.Valid = true 
} 
func main() { 
var r *Role 
r.SetCode("mi") 
if r.Code.Valid { 
    fmt.Println(r.Code) 
} 

私はここにこれを試してみた:https://play.golang.org/p/faxQUm-2lr

1

はアプリとデータベース・コードの別々のしてください。

// Role belongs to app code, no compromises. 

type Role struct { 
    Id int64 
    Code string 
} 

データベースをモデル化します。

// Database has tables with columns. 

type Table struct { 
    Name string 
    Columns []string 
} 

var RoleTable = Table{ 
    Name: "roles", 
    Columns: []string{ 
     "id", 
     "code", 
    }, 
} 

モデルとデータベースの行を1回変換するコードを書く。

// Database package needs to make it work. 

// Write a model to database row. 
type Writer struct { 
    Role 
} 

func (w *Writer) Write() []interface{} { 
    return []interface{}{ 
     w.Role.Id, 
     sql.NullString{ 
      Valid: len(w.Role.Code) > 0, 
      String: w.Role.String, 
     }, 
    } 
} 

// Read a database row into model. 
type Reader struct { 
    Id int64 
    Code sql.NullString 
} 

func (r *Reader) Scan(row *sql.Row) error { 
    return row.Scan(
     &r.Id, 
     &r.Code, 
    ) 
} 

func (r *Reader) Read() Role { 
    return Role{ 
     Id: r.Id, 
     Code: r.Code.String, 
    } 
} 

あなたのスキーマはアプリモデルから切り離されています。保存またはロードするときに、ユーザーの連絡先の詳細などの構造をフラット化できます。

// Nested struct in app code. 
type User struct { 
    TwitterProfile struct { 
     Id string 
     ScreenName string 
    } 
} 

// Database row is normalized flat. 
var UserTable = Table{ 
    Name: "users", 
    Columns: []string{ 
     "twitter_id", 
     "twitter_screen_name", 
    }, 
} 

柔軟性があります。中間構造体なしで結合行をスキャンすることもできます。

type RowMux struct { 
    vs []interface{} 
} 

func (mux *RowMux) Scan(vs ...interface{}) error { 
    mux.vs = append(mux.vs, vs...) 
    return nil 
} 

func (mux *RowMux) Mux(row *sql.Row) error { 
    return row.Scan(mux.vs...) 
} 

// Scan join rows! 
row := db.QueryRow(` 
    SELECT users.*, roles.* 
    FROM users 
    JOIN roles ON users.id = roles.user_id 
    WHERE users.twitter_id = "123" 
`) 
mux := &RowMux{} 
userReader := &UserReader{} 
userReader.Scan(mux) 
roleReader := &RoleReader{} 
roleReader.Scan(mux) 
if err := mux.Mux(row); err != nil { 
    panic(err) 
} 
user := userReader.Read() 
role := roleReader.Read() 
関連する問題