2017-02-04 3 views
1

私には2種類の変数があります。 Go playgroundを確認してください。なぜこれが起こっているのかわかりません。問題:私がModelsから得るものは、GORM First()の機能のためにそれを使用するにはstructでなければなりません。ゴランポインタの違い

コード:

package main 

import (
    "fmt" 
) 

type Test struct { 
    Test string 
} 

var Models = map[string]interface{}{ 
    "test": newTest(), 
} 

func main() { 
    test1 := Test{} 
    fmt.Println("Test 1: ") 
    fmt.Printf("%v", test1) 
    fmt.Println() 
    fmt.Println("Test 1 as pointer: ") 
    fmt.Printf("%v", &test1) 
    fmt.Println() 
    test2 := Models["test"] 
    fmt.Println("Test 2: ") 
    fmt.Printf("%v", test2) 
    fmt.Println() 
    fmt.Println("Test 2 as pointer: ") 
    fmt.Printf("%v", &test2) 

} 

func newTest() Test { 
    var model Test 
    return model 
} 
+0

ここにコードを貼り付ける必要があります。要約すると 'test1'は' Test'の型を持ち、 'test2'は' interface {} '(空のインタフェース)の型を持っています。それは別のタイプです。 – ymonad

+0

@ymonadはい、私はそれをチェックしましたが、正しい構造体に広告を戻すにはどうすればいいですか? – PumpkinSeed

+0

'map [string] interface {}'を 'map [string] Test'に変更できます。しかし、私はこれが[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)だと思います。解決したい問題がありますか? – ymonad

答えて

1

TLを情報; DR:最初のケースであなたは、印刷用タイプ*Testの値を渡しますが、後者の場合には、あなたがタイプ*interface{}の値を渡します! %v動詞は、デフォルトの書式設定を使用して書式を設定することを意味しますが、既定の書式設定は値の種類によって異なります。


ご覧の違いはfmtパッケージの実装のルールをフォーマットするだけでデフォルトです。

あなたは fmt.Printf()を使用している

タイプ interface{}としてフォーマット文字列や他の引数を取り
func Printf(format string, a ...interface{}) (n int, err error) 

。したがって、渡す値のタイプがinterface{}ではない場合、値はinterface{}の値にラップされます。

今度はあなたの例を見てみましょう:

test1 := Test{} 
// ... 
fmt.Printf("%v", &test1) 

test1はタイプTestのものであり、あなたはタイプ*Testのある&test1を渡します。これはinterface{}にラップされます。fmtのパッケージドキュメントからフォーマットルール:化合物のオブジェクトについて

は、要素がこれらの規則を使用して印刷され、再帰的に、このようなレイアウト:それへのポインタであるので

struct:    {field0 field1 ...} 
array, slice:  [elem0 elem1 ...] 
maps:    map[key1:value1 key2:value2] 
pointer to above: &{}, &[], &map[] 

struct&{}形式が使用されます。 TestにはフィールドTest stringがありますが、値を設定していないので、stringzero valueがデフォルトで空の文字列""に設定されています。だからこそ、あなたは何も見えません。

test1 := Test{"a"} 

出力がされているでしょう:

&{a} 

はのは、あなたの第二の例を見てみましょう:

test2 := Models["test"] 
// ... 
fmt.Printf("%v", &test2) 

最初の行はshort variable declarationであるあなたは、このようにそれを初期化していた場合があります、test2のタイプは、右側の式から推論されます。右側の式はindex expressionで、地図のインデックスを作成します。タイプはマップの値タイプになります。Modelsのタイプはmap[string]interface{}なのでtest2のタイプはinterface{}になります。

これまでのところとても良いです。しかし、fmt.Printf("%v", &test2)のように印刷しようとするとどうなりますか? interface{}test2へのポインターを渡すので、渡すものは*interface{}タイプで、interface{}と同じではないため、別のinterface{}値でラップされます。

だから何fmt.Printf()に渡されることはtest2変数のアドレスであること*interface{}値をラップinterface{}値、です。

そして今ここに適用される書式設定のルール:

%のVのデフォルトの形式は次のとおりです。

bool:     %t 
int, int8 etc.:   %d 
uint, uint8 etc.:  %d, %x if printed with %#v 
float32, complex64, etc: %g 
string:     %s 
chan:     %p 
pointer:     %p 

にフォーマットされる値は、ポインタ(*interface{})であるので、%v%pのデフォルト値は、

ポイントR:だから、結果は適切例えば、16進数形式でアドレス値を印刷している。:

0x1040a160 

test2から構造体を得るために

%p base 16 notation, with leading 0x 

、あなたはtype assertionを使用することができます。

t2 := Models["test"] 
test2 := t2.(Test) // test2 is of type Test 

このtest2test1のものと同じタイプを持っており、印刷するときに同じ結果を生成します。だから、むしろこのようなものでなければなりません。 Go Playgroundで試してみてください。

ベストマップに格納interface{}が既に使用され得るTestへのポインタであるように、マップに*Test値を格納する、などもローカル変数に格納ないタイプアサーションまたは必要ないであろうけれどもであろう/そのままそのまま渡される。

+0

ニースの答えは、ほとんど私はこれを発見しましたが、現在私は私の問題に解決策がありません:私はあなたのアドバイスは何ですか? _ "モデルの配列はstructsでいっぱいです。私は正しいstructのインスタンスを返すことを望んでいます。たとえば、データベーステーブルをすべて表す300の構造体があります。私はいつもテーブルのインスタンスを返したいと思っています。 "_ – PumpkinSeed

+0

@PumpkinSeed私はあなたの例を理解していない、多分あなたは新しい質問として投稿する必要がありますか? – icza

+0

私はそれを取った、私はすべてが理解できることを望む:http://stackoverflow.com/questions/42038782/golang-database-manager-api-concept-error-with-type-assertion – PumpkinSeed

1

それはフィールド(又は 要素が含まれていない場合

golangあたりドキュメントとしてサイズとアライメント保証によれば、構造体または配列型はサイズがゼロを有していますそれぞれ、0より大きいサイズを有する。 2つの異なるゼロサイズ変数はメモリ内で同じアドレスを持つことがあります。

Test 1&{}

インタフェース値はインタフェースに格納されているタイプと 関連するデータへのポインタに関する情報へのポインタ を与える2ワードのペアとして表されている理由です。

Test2interface{}で、Test2をしたがって種類記憶され、データ自体へのポインタに関する情報へのポインタを有しています。これは、型と値は