Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type switch doesn't support multiple-cases? #36616

Closed
kiwi-yan opened this issue Jan 17, 2020 · 2 comments
Closed

Type switch doesn't support multiple-cases? #36616

kiwi-yan opened this issue Jan 17, 2020 · 2 comments

Comments

@kiwi-yan
Copy link

What version of Go are you using (go version)?

$ go version
1.13.3

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOROOT="/usr/lib/golang"

I ignored some irrelevant information.

What did you do?

// ConvertFloat64 convert any type to float64 if it can.
func ConvertFloat64(v interface{}) (ret float64, err error) {
	switch val := v.(type) {
	case float64:
		return val, nil
	case float32:
		return float64(val), nil
	case uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64:
		return float64(val), nil
	default:
		err = fmt.Errorf("unsupported value to convert to float64,%v", v)
	}
	return
}

When I use multiple-cases in type swtich, error will occur:
cannot convert val (type interface {}) to type float64: need type assertion

Line 9. When I switch to single case, error won't occur.
I want to know why I can't merge these case branch.

Thank you.

What did you expect to see?

What did you see instead?

@kiwi-yan
Copy link
Author

Add:
If my code is

// ConvertFloat64 convert any type to float64 if it can.
func ConvertFloat64(v interface{}) (ret float64, err error) {
	switch val := v.(type) {
	case float64:
		return val, nil
	case float32:
		return float64(val), nil
	case uint:
		return float64(val), nil
	case uint8:
		return float64(val), nil
	case uint16:
		return float64(val), nil
	case uint32:
		return float64(val), nil
	case uint64:
		return float64(val), nil
	case int:
		return float64(val), nil
	case int8:
		return float64(val), nil
	case int16:
		return float64(val), nil
	case int32:
		return float64(val), nil
	case int64:
		return float64(val), nil
	default:
		err = fmt.Errorf("unsupported value to convert to float64,%v", v)
	}
	return
}

error won't occur.

@ianlancetaylor
Copy link
Contributor

When you use a type switch like

    switch val := v.(type) {

then if the case has multiple types, the type of val is interface{}. And Go does not permit writing float64(val) if val has type interface{}.

It's true that float64(val) can be compiled for every type in the case, but since Go is statically typed that could only be done if the compiler quietly duplicated the case for every type. The language requires that if that is what you want to do, you must do it explicitly.

See https://golang.org/ref/spec#Switch_statements :

The TypeSwitchGuard may include a short variable declaration. When that form is used, the variable is declared at the end of the TypeSwitchCase in the implicit block of each clause. In clauses with a case listing exactly one type, the variable has that type; otherwise, the variable has the type of the expression in the TypeSwitchGuard.

@golang golang locked and limited conversation to collaborators Jan 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants