在我的 Golang 可变参数函数中,处理参数的更好方法是什么?

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

Better way to deal with arguments in my golang variadic function

问题

如果在下面的可变参数函数中只有一个参数,有没有更简洁的方法来将ip2初始化为空字符串?

func myvariadic(ip ...string) {
    ip1 := ip[0]
    if len(ip) > 1 { 
        ip2 := ip[1] 
    } else {
        ip2 := ""
        ///...
    }
}

可以使用短变量声明和条件表达式来简化代码:

func myvariadic(ip ...string) {
    ip1 := ip[0]
    ip2 := ""
    if len(ip) > 1 { 
        ip2 = ip[1] 
    }
    ///...
}

这样,无论是否有第二个参数,ip2都会被初始化为空字符串。

英文:

Is there a shorter way to initialize ip2 to empty string if there is only one argument in my variadic function below?

func myvariadic(ip ...string) {
    ip1 := ip[0]
    if len(ip) > 1 { 
        ip2 := ip[1] 
    } else {
        ip2 := ""
        ///...
    }

答案1

得分: 3

你可以简单地使用以下代码:

func myvariadic(ip ...string) {
    ip1, ip2 := ip[0], ""
    if len(ip) > 1 {
        ip2 = ip[1]
    }
    fmt.Println(ip1, ip2)
}

但是不要忘记,可变参数函数可以在指定/传递可变参数的值时不传递任何参数。这意味着,即使使用零参数调用myvariadic()也是合法的(不会在编译时出错),然后甚至ip[0]也会导致运行时错误。

如果你的函数必须至少接收一个字符串,并可选地接收第二个字符串,你应该将函数的签名更改为:

func myvariadic(ip1 string, ips ...string) {
    ip2 := ""
    if len(ips) > 1 {
        ip2 = ips[1]
    }
    fmt.Println(ip1, ip2)
}

这样可以确保至少传递一个string(否则将会在编译时出错)。如果只传递一个参数,这也更高效,因为不需要分配切片(ips将使用nil)。在这里可以了解更多详细信息:https://stackoverflow.com/questions/37270743/is-it-possible-to-trigger-compile-time-error-with-custom-library-in-golang/37271129#37271129

如果参数始终是1个或2个string值,我不确定是否有必要使用可变参数,你可以简单地使用:

func myNonVariadic(ip1, ip2 string) {
    fmt.Println(ip1, ip2)
}

如果ip2不可用,只需在调用者处传递空字符串""即可。

如果你仍然想坚持使用可变参数函数,另一个选项是在函数内部不引入ip1ip2,而是直接使用ip[0]ip[1]。为了避免在传递少于2个参数时发生运行时错误,你可以自己追加一个空字符串,例如:

func myvariadic(ip ...string) {
    if len(ip) < 2 {
        ip = append(ip, "")
    }
    fmt.Println(ip[0], ip[1])
}

处理0个参数的版本如下:

func myvariadic(ip ...string) {
    for len(ip) < 2 {
        ip = append(ip, "")
    }
    fmt.Println(ip[0], ip[1])
}

后一种版本确保切片类型的ip变量至少有2个元素,即使传递了0个参数也是如此。

英文:

You may simply use:

func myvariadic(ip ...string) {
	ip1, ip2 := ip[0], &quot;&quot;
	if len(ip) &gt; 1 {
		ip2 = ip[1]
	}
	fmt.Println(ip1, ip2)
}

But don't forget that variadic functions may be called with 0 arguments specified / passed as the value for the variadic parameter. What this means is that it is also legal (not a compile-time error) to call myvariadic() with zero arguments, and then even ip[0] will cause a runtime panic.

If your function must receive at least one string and optionally a second, you should change the signature of your function to this:

func myvariadic(ip1 string, ips ...string) {
	ip2 := &quot;&quot;
	if len(ips) &gt; 1 {
		ip2 = ips[1]
	}
	fmt.Println(ip1, ip2)
}

What this guarantees is that 1 string will surely be passed (else it would be a compile-time error). This is also more efficient if only one argument is passed, as no slice allocation will be needed (nil will be used for ips). See more details on this here: https://stackoverflow.com/questions/37270743/is-it-possible-to-trigger-compile-time-error-with-custom-library-in-golang/37271129#37271129

If parameters are always 1 or 2 string values, I'm not sure variadic parameters is justified at all, you may simply use:

func myNonVariadic(ip1, ip2 string) {
	fmt.Println(ip1, ip2)
}

And simply pass the empty string &quot;&quot; at the caller if ip2 is not available.

If you still want to stick to variadic function, another option would be to not introduce ip1 and ip2 inside the function, but simply use ip[0] and ip[1]. And to avoid runtime panic if less than 2 arguments is passed, you may append an empty string yourself, e.g.:

func myvariadic(ip ...string) {
	if len(ip) &lt; 2 {
		ip = append(ip, &quot;&quot;)
	}
	fmt.Println(ip[0], ip[1])
}

And the version that also deals with 0 arguments:

func myvariadic(ip ...string) {
	for len(ip) &lt; 2 {
		ip = append(ip, &quot;&quot;)
	}
	fmt.Println(ip[0], ip[1])
}

This latter version makes sure the ip variable (of slice type) will have at least 2 elements, even if 0 is passed.

答案2

得分: 2

声明所有的局部变量并移除else。这是我能想到的另一种方式:

func myvariadic(ip ...string) {
    ip1 := ip[0]
    var ip2 string
    if len(ip) > 1 { 
        ip2 = ip[1] 
    }

    fmt.Println(ip1, ip2)
}

请注意,这只是代码的翻译,没有其他额外的内容。

英文:

Declare all locals up front and remove else. This is the only other way I could think of:

func myvariadic(ip ...string) {
    ip1 := ip[0]
    var ip2 string
    if len(ip) &gt; 1 { 
        ip2 = ip[1] 
    }

    fmt.Println(ip1,ip2)

答案3

得分: 1

你根本不需要进行初始化。在Go语言中,所有的基本类型都会被初始化为它们的默认值。

也就是说,下面的表达式是成立的。

a := ""
var b string
fmt.Println(a == b)

因此,你推断的ip2 := ""已经是你可以输入的最简洁版本了。

英文:

You don't need to initialize at all. All primitive types are initialized to their default values in Go.

IOW, this is true.

a := &quot;&quot;
var b string
fmt.Println(a == b)

https://play.golang.org/p/hwQmU4Myrp

Therefore, you inferred assignment of ip2 := &quot;&quot; is already the most succinct version you can type.

huangapple
  • 本文由 发表于 2017年6月10日 20:48:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/44473471.html
匿名

发表评论

匿名网友

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

确定