구조체에서 기본형을 배제하다

25468 단어 Go모델링tech

개요


Go는 개념 표현이 쉬운 언어다.

기본 구조체를 사용하다


type User struct {
	Name  string
	Email string
}
개념 모델을 깨닫기 시작하면 위의 코드를 보면 Name과 Email은 다른 개념이어야 하지만 같은 유형의 사람들은 구역질이 난다.
Go의 경우 Defined Type을 사용해 구조체에서 기본형을 제외할 수 있다.

기본형의 배제


type Name string
type Email string

type User struct {
	Name  Name
	Email Email
}
NameEmail의 개념은 이미 분리되었다.
이 하나만으로도 외출 후에는 별명만 붙이고 Go는 구조적으로 틀을 붙이는데 여기에 덧붙이면 콘셉트 표현도 정교해진다.
예를 들어 다음과 같은 검증을 실현할 수 있다.
package main

import (
	"fmt"
	"reflect"
	"strings"
)

type Name string
type Email string

type User struct {
	Name  Name
	Email Email
}

// ValidationProp は検査対象プロパティ
type ValidationProp interface {
	IsValid() bool
}

// IsValid は Email が定義域内かを検証する
func (src Email) IsValid() bool {
	// @ を含まないものは不可
	return strings.Contains(string(src), "@")
}

// Check は構造体内のプロパティが定義域内かを検証する
func Check(value interface{}) bool {
	v := reflect.ValueOf(value)
	t := v.Type()
	// 構造体のプロパティを 1つずつ確認
	for i := 0; i < t.NumField(); i++ {
		fv := v.Field(i)
		// ValidationProp 型の場合は検証する
		if prop, ok := fv.Interface().(ValidationProp); ok {
			if !prop.IsValid() {
				return false
			}
		}
	}
	return true
}

func main() {
	alice := User{Name: "Alice", Email: "[email protected]"}
	fmt.Printf("User: %+v, Check: %t\n", alice, Check(alice))
	// => User: {Name:Alice Email:[email protected]}, Check: true
	bob := User{Name: "Bob", Email: "bob email"}
	fmt.Printf("User: %+v, Check: %t\n", bob, Check(bob))
	// => User: {Name:Bob Email:bob email}, Check: false
}
https://play.golang.org/p/1NgYus1jBpT
위 코드에서
  • IsValid() 방법이 정의한 유형을 ValidationProp
  • 라고 부른다
  • Check() 패브릭에 포함된 ValidationProp의 적절성 결정
  • Email형에 정의IsValid()를 통해Check()의 검사 대상에 포함
  • 이(가) 구현되었습니다.
    "따라서 예를 들어,""비워두기Name""조건이 추가된 경우
    func (src Name) IsValid() bool {
    	return src != ""
    }
    
    만 추가하면 됩니다.
    추가 코드 전문
    package main
    
    import (
    	"fmt"
    	"reflect"
    	"strings"
    )
    
    type Name string
    type Email string
    
    type User struct {
    	Name  Name
    	Email Email
    }
    
    // ValidationProp は検査対象プロパティ
    type ValidationProp interface {
    	IsValid() bool
    }
    
    // IsValid は Email が定義域内かを検証する
    func (src Email) IsValid() bool {
    	// @ を含まないものは不可
    	return strings.Contains(string(src), "@")
    }
    
    // IsValid は Name が定義域内かを検証する
    func (src Name) IsValid() bool {
    	return src != ""
    }
    
    // Check は構造体内のプロパティが定義域内かを検証する
    func Check(value interface{}) bool {
    	v := reflect.ValueOf(value)
    	t := v.Type()
    	// 構造体のプロパティを 1つずつ確認
    	for i := 0; i < t.NumField(); i++ {
    		fv := v.Field(i)
    		// ValidationProp 型の場合は検証する
    		if prop, ok := fv.Interface().(ValidationProp); ok {
    			if !prop.IsValid() {
    				return false
    			}
    		}
    	}
    	return true
    }
    
    func main() {
    	alice := User{Name: "Alice", Email: "[email protected]"}
    	fmt.Printf("User: %+v, Check: %t\n", alice, Check(alice))
    	// => User: {Name:Alice Email:[email protected]}, Check: true
    	bob := User{Name: "Bob", Email: "bob email"}
    	fmt.Printf("User: %+v, Check: %t\n", bob, Check(bob))
    	// => User: {Name:Bob Email:bob email}, Check: false
    	anonymous := User{Name: "", Email: "[email protected]"}
    	fmt.Printf("User: %+v, Check: %t\n", anonymous , Check(anonymous ))
    	// => User: {Name: Email:[email protected]}, Check: false
    }
    
    
    https://play.golang.org/p/G1KOORTtpZF
    이처럼 Go는 개념을 절분하고 나중에 추가하는 것이 수월해 콘셉트 모델을 활용하기 쉽다.


    매립을 통해 (하고 싶다면) 이런 정의를 내릴 수 있다.
    type Name string
    type Email string
    
    type User struct {
    	Name
    	Email
    }
    
    변경 후 코드 전문
    package main
    
    import (
    	"fmt"
    	"reflect"
    	"strings"
    )
    
    type Name string
    type Email string
    
    type User struct {
    	Name
    	Email
    }
    
    // ValidationProp は検査対象プロパティ
    type ValidationProp interface {
    	IsValid() bool
    }
    
    // IsValid は Email が定義域内かを検証する
    func (src Email) IsValid() bool {
    	// @ を含まないものは不可
    	return strings.Contains(string(src), "@")
    }
    
    // Check は構造体内のプロパティが定義域内かを検証する
    func Check(value interface{}) bool {
    	v := reflect.ValueOf(value)
    	t := v.Type()
    	// 構造体のプロパティを 1つずつ確認
    	for i := 0; i < t.NumField(); i++ {
    		fv := v.Field(i)
    		// ValidationProp 型の場合は検証する
    		if prop, ok := fv.Interface().(ValidationProp); ok {
    			if !prop.IsValid() {
    				return false
    			}
    		}
    	}
    	return true
    }
    
    func main() {
    	alice := User{Name: "Alice", Email: "[email protected]"}
    	fmt.Printf("User: %+v, Check: %t\n", alice, Check(alice))
    	// => User: {Name:Alice Email:[email protected]}, Check: true
    	bob := User{Name: "Bob", Email: "bob email"}
    	fmt.Printf("User: %+v, Check: %t\n", bob, Check(bob))
    	// => User: {Name:Bob Email:bob email}, Check: false
    }
    
    https://play.golang.org/p/fvOzcOXodzl
    예뻐 보여요.

    좋은 웹페이지 즐겨찾기