2011-11-02 41 views
13

我使用的包裝件,gosqlite,具有帶有可變參數參數,其中它的類型是空接口的方法。通行證串切片可變參數空接口參數

func (s *Stmt) Exec(args ...interface{}) os.Error 

我可以把這個很好,如果明確地傳遞各個參數:

statement := blah() 
error := statement.Exec("hello", 3.0, true) // works fine 

然而,作爲一個可變參數對應於佔位符in操作我的SQL語句的select內,這些佔位符的數量在編譯時不知道,但在運行時動態更改取決於用戶正在做什麼。例如。我結束了與SQL類似於以下,如果用戶輸入四個值:

SELECT * FROM sky WHERE name IN (?,?,?,?) 

所以很自然,我想打電話給Exec法串片:

var values []string = getValuesFromUser() 
statement := createStatementWithSufficientNumberOfPlaceholders(len(values)) 
_ := statement.Exec(values...) // compiler doesn't like this 

這並不編譯。我可以通過創建一個空的接口切片並通過複製引用解決這個問題:

values2 := make([]interface{}, len(values)) 
for index, value := range values { values2[index] = value } 
_ := statement.Exec(values2...) // compiler happy but I'm not 

這工作正常,但感覺有點笨重。我想知道是否有一些技巧能夠將values直接傳遞給此函數,或者,如果沒有,那麼將字符串切片轉換爲空白接口的方法會更好嗎?

非常感謝。

回答

9

無法將[]string直接傳遞給...interface{}參數。這樣做需要線性時間複製(使用n + 1分配!)。如果這種語言隱藏你的話,這將是一個重大的隱藏成本。通常,將切片傳遞給可變參數只是將切片傳遞給函數。

至於其他方式這樣做,你可以通過編寫一個函數,它需要一個[]string並返回相應的[]interface{}使其更清潔。當然,你必須爲每個[]T - >[]interface{}轉換重新編寫一次,但它的功能相當簡短,而所有這些變化都是簽名。你可以使用reflection,其具有固有的運行成本,使功能「通用」,如:

valuesVal := reflect.ValueOf(values) 
... 
for i := range values2 { values2[i] = valuesVal.Index(i).Interface() } 
+0

我現在已經將轉換代碼內聯:當我添加它時,功能看起來過度。我猜這個問題最終是Go不支持我習慣於在Java和C#中使用協變數組/切片,這可能[並非壞事](http://en.wikipedia.org/wiki /Covariance_and_contravariance_(computer_science)#Arrays_in_C.23_and_Java)。 –

1

我沒有答案。而且我不認爲有一個因爲即使內置和可變參數副本追加具有相同(或兼容混凝土)元素類型「傻瓜」,但我有兩個明顯的建議:

  • 不要在其他類型的年終總結返回從getValuesFromUser()[]string(即通靜態縵[]interface{})
  • 調用statement.Exec()FUNC使[]string[]interface{}轉換。

或者在同一張第三張明顯的音符上,type statementExec(args ...string)

P.S.我自己並沒有做任何基準測試,但我不認爲這種轉換是非常昂貴的,因爲interface {}感覺像是一種參考類型,編譯器可能在幕後做了一些骯髒的詭計......然而也許不是,雖然我也很高興能夠學習實際的解決方案。

+0

感謝您的建議。然而,我認爲從'getValuesFromUser()'傳遞'[] interface {}'會比支付拷貝的價格更加錯誤。關於擴展類型:這是一個有趣的想法,但要注意Go不支持重載函數,所以它必須有不同的名稱。 –

+0

@PaulRuane不想聽起來太哲學,但我不明白這是怎麼回事,只要這對最終用戶保持隱藏(你總是可以輸入cast/assert以備將來參考)。在一個類似的話題也有更老[建議](http://stackoverflow.com/questions/3839335/any-sensible-solution-to-the-lack-of-array-slice-covariance-in-go/5370177# 5370177)SteveMcQuark說我覺得有意思。 – ypb