Go函数的点表示法

huangapple go评论82阅读模式
英文:

Go functions dot notation

问题

我想要构建这样的代码:

finalResult, err := Function1(任意类型)
    .Function2(任意类型)
    .Function3(任意类型)

类似于JavaScript中的Promise,但不一定是完全相同的概念。或者类似于Java中的嵌套方法。我只是希望避免为相同的任务编写更多的代码。

我不想这样做:

result, err := new(Function1(任意类型)) //或 *Function1(任意类型)
if err != nil {...}
result1, err := result.Function2(任意类型)
if err != nil {...}
finalResult, err := result1.Function3(任意类型)
if err != nil {...}

我已经尝试了几种使用结构体和接口的选项,但是没有得到任何结果。

如果我的语法有错误,请原谅。我的英语水平还不够好。

谢谢,

David

英文:

I want to build this:

finalResult, err := Function1(whatever type)
    .Function2(whatever type)
    .Function3(whatever type)

Something similar to promises in javascript but not necessarily the same concepts. Or similar to nested methods in Java. I just pretend avoid more code for the same tasks.

I don't want to do this :

result, err := new(Function1(whatever type)) //or *Function1(whatever type)
if err != nil {...}
result1, err := result.Function2(whatever type)
if err != nil {...}
finalResult, err := result1.Function3(whatever type)
if err != nil {...}

I've been trying with several options with structs and interfaces but I can't get any result.

My apology if I have a mistake in my grammar. I'm not still so good with my skill English.

Thanks,

David

答案1

得分: 4

我认为你指的是流畅的API设计模式。在这种模式下,你会一次又一次地返回相同的对象,或者在Go语言中返回相同的结构体。

然而,这种模式不允许你返回元组或多个返回类型。你只能返回一个对象。

以下是示例代码:

package main

import (
	"fmt"
)

type Object struct {
	Value string
	Error error
}

func (o *Object) Before(s string) *Object {
	o.Value = s + o.Value
	// 如果需要,可以添加错误
	// o.Error = error.New(...)
	return o
}

func (o *Object) After(s string) *Object {
	// 也可以检查错误
	if o.Error != nil {
		o.Value = o.Value + s
	}
	return o
}

func main() {
	x := Object{}

	x.
		Before("123").
		After("456").
		After("789").
		Before("0")

	if x.Error != nil {
		// 处理错误
	}
	fmt.Println(x.Value)
}

编辑:sberry的回答提供了一个很好的想法。在Object结构体本身上添加一个错误状态,这样可以在每个函数调用中检查错误。


由于你是新用户,请记得评估所有的答案,并选择你认为最好的答案。

英文:

I think you mean the Fluent API design pattern. You return the same Object, or struct in Go, over and over.

This pattern does not allow you to return a tuple, or multiple return types though. You can only return one object.

https://play.golang.org/p/9PceZwi1a3

package main

import (
	"fmt"
)

type Object struct {
	Value string
	Error error
}

func (o *Object) Before(s string) *Object {
	o.Value = s + o.Value
	// add an error if you like
   	// o.Error = error.New(...)
	return o
}

func (o *Object) After(s string) *Object {
    // could check for errors too
    if o.Error != nil {
	    o.Value = o.Value + s
    }
	return o
}

func main() {
	x := Object{}

	x.
		Before("123").
		After("456").
		After("789").
		Before("0")

	if x.Error != nil {
		// handle error
	}
	fmt.Println(x.Value)
}

Edit: sberry's answer had a good idea. Add an Error state on the Object struct itself which could allow u to check for errors in each func call.


Since you are new, please remember to evaluate all answers and mark the best one you believe lead you the answer.

答案2

得分: 0

这样做的唯一方法是将每个FunctionX作为接收器的方法(如果你要改变状态,则最可能是指针接收器),并使它们每个都返回接收器。代码如下:

type someNumber struct {
    n int32
}

func (s *someNumber) Add(i int32) *someNumber {
    s.n += i
    return s
}

func (s *someNumber) Multiply(i int32) *someNumber {
    s.n *= i
    return s
}

func (s *someNumber) Subtract(i int32) *someNumber {
    s.n -= i
    return s
}

func main() {
    num := &someNumber{n: 0}
    result := num.Add(5).Multiply(4).Subtract(10)
    fmt.Println(result.n)
}

你也可以在someNumber上设置错误,并在最后进行检查。

如果你想要实际传递错误,那么你需要像这样做:

func Function1(a int, err error) (int, error) {
    if err != nil {
        return a, err
    }
    return a, nil
}

func Function2(a int, err error) (int, error) {
    if err != nil {
        return a, err
    }
    return a*2, nil
}


func Function3(a int, err error) (int, error) {
    if err != nil {
        return a, err
    }
    return a*3, nil
}

func main() {
    a, err := Function3(Function2(Function1(1, nil)))
    fmt.Println(a, err)    
}

但是,似乎你正在寻找错误单子(Error Monad)所带来的行为类型,而Go语言中并不存在这种类型。

英文:

The only way to do this would be to have each FunctionX be a method on a receiver (most likely a pointer receiver if you are mutating state) and have them each return the receiver. Like so

type someNumber struct {
	n int32
}

func (s *someNumber) Add(i int32) *someNumber {
	s.n += i
	return s
}

func (s *someNumber) Multiply(i int32) *someNumber {
	s.n *= i
	return s
}

func (s *someNumber) Subtract(i int32) *someNumber {
	s.n -= i
	return s
}

func main() {
	num := &someNumber{n: 0}
	result := num.Add(5).Multiply(4).Subtract(10)
	fmt.Println(result.n)
}

You could set and error on the someNumber as well, and check it at the end.

If you are looking to actually carry through the error, then you would need to do something like this.

func Function1(a int, err error) (int, error) {
	if err != nil {
		return a, err
	}
	return a, nil
}

func Function2(a int, err error) (int, error) {
	if err != nil {
		return a, err
	}
	return a*2, nil
}


func Function3(a int, err error) (int, error) {
	if err != nil {
		return a, err
	}
	return a*3, nil
}

func main() {
	a, err := Function3(Function2(Function1(1, nil)))
	fmt.Println(a, err)	
}

But, it seems like you are looking for the type of behavior an Error Monad would bring and that does not exist in Go.

huangapple
  • 本文由 发表于 2017年7月22日 23:50:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/45256433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定