Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Impossible type switch case

Tags:

go

This program does not compile:

package main

type Validator struct {
}

// Error implements error interface
func (v *Validator) Error() string {
    return ""
}

func test() error {
    return &Validator{}
}

func main() {
    switch test().(type) {
    case nil:
        println("No error")
    case Validator:
        println("Validation error")
        return
    default:
        println("Unknown error")
        return
    }
}

The error is:

prog.go:19: impossible type switch case: test() (type error) cannot have dynamic type Validator (missing Error method)

But Validator struct has method Error.

like image 287
warvariuc Avatar asked Jul 06 '14 07:07

warvariuc


People also ask

What is switch case in typescript?

Switch case is an important programming construct used for shifting between different parts of the code blocks based on different application logic. Different programming languages have their own implementation of the switch case expressions. TypeScript also has support for switch cases with the expression having any type.

What are some examples of using the SWITCH CASE statement?

Let’s take some examples of using the switch…case statement. The following example shows a simple switch...case example that shows a message based on the target Id: In this example, the targetId is set to btnDelete. The switch...case statement compares the targetId with a list of values.

When to throw an exception in a switch case?

tl;dr- Yes, it's generally proper to throw an exception whenever the code attempts to do something that it wasn't designed for, including unexpected defaulting in a switch. Scenario 1: Dense logic, where all cases ought to be handled properly.

What is the default clause in the SWITCH CASE statement?

By convention, the default clause is the last clause in the switch...case statement. However, it doesn’t need to be so. Let’s take some examples of using the switch…case statement.


2 Answers

You have two different types, Validator and the pointer type *Validator, and these two types have different method sets.

You have only defined an Error() method for the pointer while Validator doesn't have this method.

What you can do is the following change:

// Error implements error interface
func (v Validator) Error() string {
    return ""
}

...

case *Validator, Validator: // You are actually getting a *Validator

This implements Error() for both Validator and *Validator. As the Go specification says:

The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T)

like image 193
ANisus Avatar answered Oct 12 '22 20:10

ANisus


The compiler is correct. Validator type does not implement Error, *Validator does. Validator and *Validator are different types. Just replace the former with the latter in the type switch:

switch test().(type) {
case nil:
    println("No error")
case *Validator:
    println("Validation error")
    return
default:
    println("Unknown error")
    return
}

Working example on the Go Playground: http://play.golang.org/p/aWqzPXweiA

like image 38
Ainar-G Avatar answered Oct 12 '22 21:10

Ainar-G