From 2a4217d27b611d8984ba61fb34fe9c63a2f029e1 Mon Sep 17 00:00:00 2001 From: CC11001100 Date: Tue, 10 Jan 2023 11:28:42 +0800 Subject: [PATCH 1/2] add set default --- README.md | 175 ++++++++++++++++++++++++++++- examples/{ => basic_usage}/main.go | 11 +- examples/default_func/main.go | 56 +++++++++ examples/set_default/main.go | 34 ++++++ examples/set_default_func/main.go | 56 +++++++++ variable_parameter.go | 21 +++- 6 files changed, 342 insertions(+), 11 deletions(-) rename examples/{ => basic_usage}/main.go (51%) create mode 100644 examples/default_func/main.go create mode 100644 examples/set_default/main.go create mode 100644 examples/set_default_func/main.go diff --git a/README.md b/README.md index 494343b..53bb756 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ go get -u github.com/golang-infrastructure/go-variable-parameter ``` # 三、Example - +## 3.1 TakeFirstParamOrDefault ```go package main @@ -23,26 +23,191 @@ type FooOptions struct { Bar int } -var DefaultFooOptions = FooOptions{ +var DefaultFooOptions = &FooOptions{ Foo: "default foo", Bar: 10, } -func Foo(optionsVariableParams ...FooOptions) { - // 如果传递了options则使用传递的,如果没传递则使用默认的 +func Foo(optionsVariableParams ...*FooOptions) { + // 如果传递了options则使用传递的取出数组中的第一个元素返回,如果没传递则使用给出的默认值,适合默认值是一个固定的值的时候用 options := variable_parameter.TakeFirstParamOrDefault(optionsVariableParams, DefaultFooOptions) + + // 后面的代码就可以直接使用options来操作啦 + fmt.Println(options.Foo) + +} + +func main() { + + // 不传递参数 + Foo() // Output: default foo + + // 传递参数 + Foo(&FooOptions{Foo: "custom foo"}) // Output: custom foo + +} +``` + + +## 3.2 TakeFirstParamOrDefaultFunc +```go +package main + +import ( + "fmt" + variable_parameter "github.com/golang-infrastructure/go-variable-parameter" + "time" +) + +type FooOptions struct { + Foo string + Bar int +} + +func NewFooOptions() *FooOptions { + + // 假装有耗时操作 + time.Sleep(time.Second * 1) + + return &FooOptions{ + Foo: "default foo", + Bar: 10, + } +} + +func Foo(optionsVariableParams ...*FooOptions) { + // 如果后面可能会涉及到对options的修改之类的,则options无法使用单例,可能得每次都重新创建一个新的,则可以使用一个默认值的函数,仅在需要默认值的时候才运行 + options := variable_parameter.TakeFirstParamOrDefaultFunc(optionsVariableParams, func() *FooOptions { + // 如果初始化比较耗时或者觉得仅在必要的时候才创建比较好可以用这种默认函数的方式,此函数仅在未传递参数时运行 + return NewFooOptions() + }) + + // 后面的代码就可以直接使用options来操作啦 fmt.Println(options.Foo) } func main() { + // 传递参数 + start := time.Now() + Foo(&FooOptions{Foo: "custom foo"}) + cost := time.Now().Sub(start) + fmt.Println("传递参数时耗时:" + cost.String()) + // Output: + // custom foo + // 传递参数时耗时:0s + + // 不传递参数 + start = time.Now() + Foo() + cost = time.Now().Sub(start) + fmt.Println("不传递参数时耗时:" + cost.String()) + // Output: + // default foo + // 不传递参数时耗时:1.0136631s + +} +``` + + +## 3.3 SetDefaultParam +```go +package main + +import ( + "fmt" + variable_parameter "github.com/golang-infrastructure/go-variable-parameter" +) + +type FooOptions struct { + Foo string + Bar int +} + +var DefaultFooOptions = &FooOptions{ + Foo: "default foo", + Bar: 10, +} + +func Foo(options ...*FooOptions) { + // 如果没有传递参数的话,则设置一个默认的参数 + options = variable_parameter.SetDefaultParam(options, DefaultFooOptions) + + // 后面的代码就可以直接使用options[0]来操作而不必担心越界 + fmt.Println(options[0].Foo) +} + +func main() { + + // 传递参数 + Foo(&FooOptions{Foo: "custom foo"}) // Output: custom foo + // 不传递参数 Foo() // Output: default foo +} +``` + + +## 3.4 SetDefaultParamByFunc +```go +package main + +import ( + "fmt" + variable_parameter "github.com/golang-infrastructure/go-variable-parameter" + "time" +) + +type FooOptions struct { + Foo string + Bar int +} + +func NewFooOptions() *FooOptions { + + // 假装有耗时操作 + time.Sleep(time.Second * 1) + + return &FooOptions{ + Foo: "default foo", + Bar: 10, + } +} + +func Foo(options ...*FooOptions) { + // 如果后面可能会涉及到对options[0]的修改之类的,则options[0]无法使用单例,可能得每次都重新创建一个新的,则可以使用一个默认值函数,仅在未传递参数的时候才会执行 + options = variable_parameter.SetDefaultParamByFunc(options, func() *FooOptions { + // 如果初始化比较耗时或者觉得仅在必要的时候才创建比较好可以用这种默认函数的方式,此函数仅在未传递参数时运行 + return NewFooOptions() + }) + + // 后面的代码就可以直接使用options[0]来操作啦 + fmt.Println(options[0].Foo) +} + +func main() { + // 传递参数 - Foo(FooOptions{Foo: "custom foo"}) // Output: custom foo + start := time.Now() + Foo(&FooOptions{Foo: "custom foo"}) + cost := time.Now().Sub(start) + fmt.Println("传递参数时耗时:" + cost.String()) + // Output: + // custom foo + // 传递参数时耗时:0s + + // 不传递参数 + start = time.Now() + Foo() + cost = time.Now().Sub(start) + fmt.Println("不传递参数时耗时:" + cost.String()) + // Output: + // default foo + // 不传递参数时耗时:1.0136631s } ``` + diff --git a/examples/main.go b/examples/basic_usage/main.go similarity index 51% rename from examples/main.go rename to examples/basic_usage/main.go index 9faae0c..6c021ff 100644 --- a/examples/main.go +++ b/examples/basic_usage/main.go @@ -10,15 +10,18 @@ type FooOptions struct { Bar int } -var DefaultFooOptions = FooOptions{ +var DefaultFooOptions = &FooOptions{ Foo: "default foo", Bar: 10, } -func Foo(optionsVariableParams ...FooOptions) { - // 如果传递了options则使用传递的,如果没传递则使用默认的 +func Foo(optionsVariableParams ...*FooOptions) { + // 如果传递了options则使用传递的取出数组中的第一个元素返回,如果没传递则使用给出的默认值,适合默认值是一个固定的值的时候用 options := variable_parameter.TakeFirstParamOrDefault(optionsVariableParams, DefaultFooOptions) + + // 后面的代码就可以直接使用options来操作啦 fmt.Println(options.Foo) + } func main() { @@ -27,6 +30,6 @@ func main() { Foo() // Output: default foo // 传递参数 - Foo(FooOptions{Foo: "custom foo"}) // Output: custom foo + Foo(&FooOptions{Foo: "custom foo"}) // Output: custom foo } diff --git a/examples/default_func/main.go b/examples/default_func/main.go new file mode 100644 index 0000000..53dd655 --- /dev/null +++ b/examples/default_func/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + variable_parameter "github.com/golang-infrastructure/go-variable-parameter" + "time" +) + +type FooOptions struct { + Foo string + Bar int +} + +func NewFooOptions() *FooOptions { + + // 假装有耗时操作 + time.Sleep(time.Second * 1) + + return &FooOptions{ + Foo: "default foo", + Bar: 10, + } +} + +func Foo(optionsVariableParams ...*FooOptions) { + // 如果后面可能会涉及到对options的修改之类的,则options无法使用单例,可能得每次都重新创建一个新的,则可以使用一个默认值的函数,仅在需要默认值的时候才运行 + options := variable_parameter.TakeFirstParamOrDefaultFunc(optionsVariableParams, func() *FooOptions { + // 如果初始化比较耗时或者觉得仅在必要的时候才创建比较好可以用这种默认函数的方式,此函数仅在未传递参数时运行 + return NewFooOptions() + }) + + // 后面的代码就可以直接使用options来操作啦 + fmt.Println(options.Foo) +} + +func main() { + + // 传递参数 + start := time.Now() + Foo(&FooOptions{Foo: "custom foo"}) + cost := time.Now().Sub(start) + fmt.Println("传递参数时耗时:" + cost.String()) + // Output: + // custom foo + // 传递参数时耗时:0s + + // 不传递参数 + start = time.Now() + Foo() + cost = time.Now().Sub(start) + fmt.Println("不传递参数时耗时:" + cost.String()) + // Output: + // default foo + // 不传递参数时耗时:1.0136631s + +} diff --git a/examples/set_default/main.go b/examples/set_default/main.go new file mode 100644 index 0000000..c65afd9 --- /dev/null +++ b/examples/set_default/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + variable_parameter "github.com/golang-infrastructure/go-variable-parameter" +) + +type FooOptions struct { + Foo string + Bar int +} + +var DefaultFooOptions = &FooOptions{ + Foo: "default foo", + Bar: 10, +} + +func Foo(options ...*FooOptions) { + // 如果没有传递参数的话,则设置一个默认的参数 + options = variable_parameter.SetDefaultParam(options, DefaultFooOptions) + + // 后面的代码就可以直接使用options[0]来操作而不必担心越界 + fmt.Println(options[0].Foo) +} + +func main() { + + // 传递参数 + Foo(&FooOptions{Foo: "custom foo"}) // Output: custom foo + + // 不传递参数 + Foo() // Output: default foo + +} diff --git a/examples/set_default_func/main.go b/examples/set_default_func/main.go new file mode 100644 index 0000000..39e67f6 --- /dev/null +++ b/examples/set_default_func/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + variable_parameter "github.com/golang-infrastructure/go-variable-parameter" + "time" +) + +type FooOptions struct { + Foo string + Bar int +} + +func NewFooOptions() *FooOptions { + + // 假装有耗时操作 + time.Sleep(time.Second * 1) + + return &FooOptions{ + Foo: "default foo", + Bar: 10, + } +} + +func Foo(options ...*FooOptions) { + // 如果后面可能会涉及到对options[0]的修改之类的,则options[0]无法使用单例,可能得每次都重新创建一个新的,则可以使用一个默认值函数,仅在未传递参数的时候才会执行 + options = variable_parameter.SetDefaultParamByFunc(options, func() *FooOptions { + // 如果初始化比较耗时或者觉得仅在必要的时候才创建比较好可以用这种默认函数的方式,此函数仅在未传递参数时运行 + return NewFooOptions() + }) + + // 后面的代码就可以直接使用options[0]来操作啦 + fmt.Println(options[0].Foo) +} + +func main() { + + // 传递参数 + start := time.Now() + Foo(&FooOptions{Foo: "custom foo"}) + cost := time.Now().Sub(start) + fmt.Println("传递参数时耗时:" + cost.String()) + // Output: + // custom foo + // 传递参数时耗时:0s + + // 不传递参数 + start = time.Now() + Foo() + cost = time.Now().Sub(start) + fmt.Println("不传递参数时耗时:" + cost.String()) + // Output: + // default foo + // 不传递参数时耗时:1.0136631s + +} diff --git a/variable_parameter.go b/variable_parameter.go index 6739c5e..03b7da6 100644 --- a/variable_parameter.go +++ b/variable_parameter.go @@ -1,6 +1,6 @@ package variable_parameter -// TakeFirstParam 获取可变参数的第一个参数 +// TakeFirstParam 获取传递的可变参数,如果没有传递的话,则返回参数对应的默认值 func TakeFirstParam[T any](parameters []T) T { if len(parameters) > 0 { return parameters[0] @@ -10,7 +10,7 @@ func TakeFirstParam[T any](parameters []T) T { } } -// TakeFirstParamOrDefault 获取可变参数的第一个参数,如果没有传的话则使用默认值 +// TakeFirstParamOrDefault 获取传递的可变参数,如果没有传的话则使用给定的默认值 func TakeFirstParamOrDefault[T any](parameters []T, defaultValue T) T { if len(parameters) > 0 { return parameters[0] @@ -19,6 +19,7 @@ func TakeFirstParamOrDefault[T any](parameters []T, defaultValue T) T { } } +// TakeFirstParamOrDefaultFunc 获取传递的可变参数,如果没有传的话则执行给定的defaultValueFunc来获取默认值,如果传递的话defaultValueFunc函数不会被执行 func TakeFirstParamOrDefaultFunc[T any](parameters []T, defaultValueFunc func() T) T { if len(parameters) > 0 { return parameters[0] @@ -26,3 +27,19 @@ func TakeFirstParamOrDefaultFunc[T any](parameters []T, defaultValueFunc func() return defaultValueFunc() } } + +// SetDefaultParam 如果传递了参数啥都不会做,如果没有传递的话则把给定的defaultValue放到parameters中,这样后面就可以直接使用parameters[0]的形式使用参数而不必担心越界 +func SetDefaultParam[T any](parameters []T, defaultValue T) []T { + if len(parameters) != 0 { + return parameters + } + return append(parameters, defaultValue) +} + +// SetDefaultParamByFunc 如果传递了参数啥都不会做,如果没有传递的话则执行defaultValueFunc来获取一个默认值,并把得到的默认值放到parameters中,这样后面就可以直接使用parameters[0]的形式使用参数而不必担心越界 +func SetDefaultParamByFunc[T any](parameters []T, defaultValueFunc func() T) []T { + if len(parameters) != 0 { + return parameters + } + return append(parameters, defaultValueFunc()) +} From ee4c6fd0ab8882564cac579bfd42778d9ac18fc8 Mon Sep 17 00:00:00 2001 From: CC11001100 Date: Tue, 10 Jan 2023 11:32:53 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++++ examples/set_default/main.go | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/README.md b/README.md index 53bb756..c8c61da 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,10 @@ func Foo(options ...*FooOptions) { // 如果没有传递参数的话,则设置一个默认的参数 options = variable_parameter.SetDefaultParam(options, DefaultFooOptions) + // 为什么不适用这种方式来操作呢?也许这样更简单? + // 在递归互相调用的时候切片中可能会被重复放入默认值,尤其是在有很多的重载之类的或者高内聚的代码中会互相调用问题尤其明显 + //options = append(options, DefaultFooOptions) + // 后面的代码就可以直接使用options[0]来操作而不必担心越界 fmt.Println(options[0].Foo) } @@ -146,6 +150,7 @@ func main() { Foo() // Output: default foo } + ``` diff --git a/examples/set_default/main.go b/examples/set_default/main.go index c65afd9..a5c7fb1 100644 --- a/examples/set_default/main.go +++ b/examples/set_default/main.go @@ -19,6 +19,10 @@ func Foo(options ...*FooOptions) { // 如果没有传递参数的话,则设置一个默认的参数 options = variable_parameter.SetDefaultParam(options, DefaultFooOptions) + // 为什么不适用这种方式来操作呢?也许这样更简单? + // 在递归互相调用的时候切片中可能会被重复放入默认值,尤其是在有很多的重载之类的或者高内聚的代码中会互相调用问题尤其明显 + //options = append(options, DefaultFooOptions) + // 后面的代码就可以直接使用options[0]来操作而不必担心越界 fmt.Println(options[0].Foo) }