Slide 1

Slide 1 text

Жизнь без generics

Slide 2

Slide 2 text

Radio-T #399 http://www.radio-t.com

Slide 3

Slide 3 text

Контейнеры m := make(map[string]int)! m["answer"] = 42! if len(m) > 0 {! ! delete(m, "answer")! }! ! func make(Type, size IntegerType) Type! func len(v Type) int! func delete(m map[Type]Type1, key Type)

Slide 4

Slide 4 text

Свои контейнеры type StringIntMapTS struct {! ! l sync.RWMutex! ! data map[string]int! }! ! func NewStringIntMapTS(cap int) *StringIntMapTS {! ! return &StringIntMapTS{! ! ! data: make(map[string]int, cap),! ! }! }! ! func (m *StringIntMapTS) Len() int {! ! m.l.RLock()! ! l := len(m.data)! ! m.l.RUnlock()! ! return l! }! ! func (m *StringIntMapTS) Get(key string) (v int, k bool) {! ! m.l.RLock()! ! value, ok = m.data[key]! ! m.l.RUnlock()! ! return! }

Slide 5

Slide 5 text

Свои контейнеры type MapTS struct {! ! l sync.RWMutex! ! data map[interface{}]interface{}! }! ! func NewMapTS(cap int) *MapTS {! ! return &MapTS{! ! ! data: make(map[interface{}]interface{}, cap),! ! }! }! ! func (m *MapTS) Len() int {! ! m.l.RLock()! ! l := len(m.data)! ! m.l.RUnlock()! ! return l! }! ! func (m *MapTS) Get(key interface{}) (v interface{}, k bool) {! ! m.l.RLock()! ! value, ok = m.data[key]! ! m.l.RUnlock()! ! return! }

Slide 6

Slide 6 text

Свои контейнеры • builtin’ы особенные: new, make, append, copy, delete, len, cap, close • range

Slide 7

Slide 7 text

Итого 1. Свои контейнеры нужно писать руками для каждого типа, или использовать interface{}

Slide 8

Slide 8 text

Функциональный подход type Thing struct {! ! F int! }! ! type Things []Thing! ! myThings := &Things{...}! myThings = Where(myThings, func(t *Thing) { t.F > 42 })! myThings = SortBy(myThings, func(a, b *Thing) bool { return a.F < b.F })

Slide 9

Slide 9 text

Наследование и полиморфизм class Base! {! public:! ! virtual void F2() {! ! ! printf("Base::F2()\n");! ! ! this->F3();! ! }! ! virtual void F3() {! ! ! printf("Base::F3()\n");! ! }! };! ! class Derived : public Base! {! public:! ! virtual void F1() {! ! ! printf("Derived::F1()\n");! ! ! this->F2();! ! }! ! virtual void F3() {! ! ! printf("Derived::F3()\n");! ! }! };! ! int main()! {! ! (new Derived)->F1();! } type Base struct{}! ! func (this *Base) F2() {! ! println("Base::F2()")! ! this.F3()! }! ! func (this *Base) F3() {! ! println("Base::F3()")! }! ! type Derived struct {! ! Base! }! ! func (this *Derived) F1() {! ! println("Derived::F1()")! ! this.F2()! }! ! func (this *Derived) F3() {! ! println("Derived::F3()")! }! ! func main() {! ! new(Derived).F1()! }

Slide 10

Slide 10 text

Наследование и полиморфизм Derived::F1()! Base::F2()! Derived::F3() Derived::F1()! Base::F2()! Base::F3()

Slide 11

Slide 11 text

Итого 1. Свои контейнеры нужно писать руками для каждого типа, или использовать interface{} 2. Полиморфизма нет

Slide 12

Slide 12 text

Полиморфизм type F3er interface {! ! F3()! }! ! type Base struct {! ! F3er F3er! }! ! func (this *Base) F2() {! ! println("Base::F2()")! ! this.F3er.F3()! }! ! func (this *Base) F3() {! ! println("Base::F3()")! } type Derived struct {! ! Base! }! ! func (this *Derived) F1() {! ! println("Derived::F1()")! ! this.F2()! }! ! func (this *Derived) F3() {! ! println("Derived::F3()")! }! ! func main() {! ! d := new(Derived)! ! d.F3er = d! ! d.F1()! }

Slide 13

Slide 13 text

Полиморфизм type Interface interface {! ! Len() int! ! Less(i, j int) bool! ! Swap(i, j int)! }! ! type ByAge []Person! func (a ByAge) Len() int { return len(a) }! func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }! func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }! ! sort.Sort(ByAge(people))

Slide 14

Slide 14 text

Итого 1. Свои контейнеры нужно писать руками для каждого типа, или использовать interface{} 2. Полиморфизма нет

Slide 15

Slide 15 text

Функциональный подход func Merge(! a map[_typeKey_]_typeValue_,! b map[_typeKey_]_typeValue_)

Slide 16

Slide 16 text

Свои контейнеры type (! ! _typeKey_ string! ! _typeValue_ int! )! ! type _TypeKey__TypeValue_MapTS struct {! ! l sync.RWMutex! ! data map[_typeKey_]_typeValue_! }! ! func New_TypeKey__TypeValue_MapTS(cap int) *_TypeKey__TypeValue_MapTS {! ! return &_TypeKey__TypeValue_MapTS{! ! ! data: make(map[_typeKey_]_typeValue_, cap),! ! }! }

Slide 17

Slide 17 text

Свои контейнеры type StringIntMapTS struct {! ! l sync.RWMutex! ! data map[string]int! }! ! func NewStringIntMapTS(cap int) *StringIntMapTS {! ! return &StringIntMapTS{! ! ! data: make(map[string]int, cap),! ! }! }

Slide 18

Slide 18 text

gogen https://github.com/AlekSi/gogen! https://github.com/AlekSi/gogen-library

Slide 19

Slide 19 text

Итого 1. Свои контейнеры нужно писать руками для каждого типа, или использовать interface{} 2. Полиморфизма нет

Slide 20

Slide 20 text

! ! ! ! ! ! https://github.com/AlekSi/gogen! https://github.com/AlekSi/gogen-library