2015-08-14 3 views
2

У Golang есть три оператора точек (...), который выгружает каждый элемент среза в качестве собственного аргумента при использовании с вызовом функции, но похоже, что подобный механик не может быть использован с инициализатором структуры.Инициализация структуры с данными среза

Есть ли способ уменьшить беспорядок кода, не обращаясь к каждому элементу в срезе при инициализации структуры?

Можно ли добавить значение в инициализированную структуру по одному или получить доступ к некоторому индексу внутри цикла for?

(я полагаю, можно было бы получить доступ к прямому местоположению в памяти инициализируются структуры - но я бы предпочел не делать этого)

Следующими не работает: (ошибка синтаксиса)

type Stats struct { 
    Total uint64 

    ICMP uint64 

    UDP uint64 
    TCP uint64 

    FTP uint64 
    HTTP uint64 
    MAIL uint64 
    P2P uint64 
} 

func newStats(slice [][]byte) *Stats { 
    var tmp [8]uint64 
    var err error 

    for i, val := range slice { 
     tmp[i], err = strconv.ParseUint(string(val), 10, 32) 
     if err != nil { 
      // Handle error 
     } 
    } 

    return &Stats{tmp...} // Syntax error 
} 

Ни делает это: (конечно)

return &Stats{ 
    for{ <code> } 
} 

Это работает, но я надеюсь на идиоматический, более быстрый способ, без синтаксической копировании

return &Stats{ 
    tmp[0], 
    tmp[1], 
    tmp[2], 
    tmp[3], 
    tmp[4], 
    tmp[5], 
    tmp[6], 
    tmp[7], 
} 
+0

Я думаю, что это может быть плохим подход. Что делать, если порядок полей меняется? Что делать, если поля добавляются/удаляются? Я предлагаю всегда использовать явный вид (т. Е. 'T {A: s [0], B: s [1],/* ... * /}'). –

+1

Возможно, это так, и это невозможно в первую очередь. Это только заставило меня задуматься. – hiqluid

ответ

0

Единственный способ, которым это действительно может быть сделано, - использовать небезопасные и copy, как вы намекаете, но даже тогда вы можете столкнуться с проблемами выравнивания. Другой «компактный» способ - использовать reflect и цикл for по полю, но это будет медленным и не очень идиоматичным.

Единственным возможным способом является, возможно, ввести свой собственный синтаксис и написать скрипт генератора, который будет вызван на go generate, который будет автоматически преобразовывать Struct{slice...} в Struct{slice[0], slice[1] ... , slice[n] } где n это число полей, но вам придется свернуть, что твой собственный.

0

В дополнение к предложениям Jsor вы можете создать метод NewStats, который принимает эллиптический аргумент и использует его вместо первого примера.

Его не идиоматические либо, но вы бы уменьшить беспорядок в коде и придется писать уродливую часть только один раз ...

+0

Я собирался упомянуть об этом, но его пример уже был в методе 'newStats', поэтому я решил, что он лишний. – LinearZoetrope