BY MTK- neuropilot - backend
定義接口進行 類似extends func 去修改
在 Golang 中,interface 其中一個功能就是可以使用 interface 定義行為
,也就是說 interface 中可以定義一些方法來表示一個對象的行為,而當我們有自定義
的型態假設想要擁有這些行為,就是去實踐
interface 裡面的方法
grpahql-go 的 extensions() 的接口講解
// grpahql-go
type ExtendedError interface {
error
Extensions() map[string]interface{}
}
定義了 ExtendedError 的接口 必須有
map[string]interface{}
的型態backend 是這樣宣告的
type Error struct {
Type Type
Message string
cause error
}
// Error message
func (e *Error) Error() string {
return e.Message
}
// Cause of the original error
func (e *Error) Cause() string {
if e.cause != nil {
return e.cause.Error()
}
return ""
}
// Extensions for graphQL extension
func (e *Error) Extensions() map[string]interface{} {
if e.cause != nil {
log.Error().Err(e.cause).Msg("graphql error report")
}
return map[string]interface{}{
"code": e.Type.Code(),
"type": e.Type,
}
}
// New creates a new error
func New(t Type, msg string, err error) error {
return &Error{
Type: t,
Message: msg,
cause: err,
}
}
新建 error時 使用 New()這個function 並且回傳的是 指標型態 可以在Context當中操控同一個記憶體位置
type Person struct {
name string
}
func main() {
p := Person{name: "Alena"}
// shallow copy
p2 := p
fmt.Printf("%+v\n", p) // {name:Alena}
fmt.Printf("%+v\n", p2) // {name:Alena}
// change the copied name
p2.name = "Not Alena"
fmt.Printf("%+v\n", p) // {name:Alena}
fmt.Printf("%+v\n", p2) // {name: Not Alena}
}
package main
import "fmt"
type Person struct {
name string
}
func main() {
p := Person{name: "Alena"}
// shallow copy
p2 := &p
fmt.Printf("%+v\n", p) // {name:Alena}
fmt.Printf("%+v\n", p2) // {name:Alena}
// change the copied name
p2.name = "Not Alena"
fmt.Printf("%+v\n", p) // {name:Alena}
fmt.Printf("%+v\n", p2) // {name: Not Alena}
}
差別在於 賦值時 p2 := p // 淺複製
p2:= &p // 深複製
如果沒有用指標則會導致淺複製的行為,並不是操控同一個 Struct。
當backend 最後return 回傳指標 &error 自定義的 Struct 並且實現 Extensions()這個function
func FormatError(err error) FormattedError {
switch err := err.(type) {
case FormattedError:
return err
case *Error:
ret := FormattedError{
Message: err.Error(),
Locations: err.Locations,
Path: err.Path,
}
if err := err.OriginalError; err != nil {
if extended, ok := err.(ExtendedError); ok {
ret.Extensions = extended.Extensions()
}
}
return ret
case Error:
return FormatError(&err)
default:
return FormattedError{
Message: err.Error(),
Locations: []location.SourceLocation{},
}
}
}
判斷 是否有error 在進行型別判斷 是否符合 ExtendedError 的interface 若是符合就會進行 call ret.Extensions = extended.Extensions()