{
  "$type": "site.standard.document",
  "canonicalUrl": "https://rednafi.com/go/type-assertion-vs-type-switches/",
  "description": "Master Go type assertions with i.(T) syntax and type switches. Extract concrete types from interfaces safely with ok idiom examples.",
  "path": "/go/type-assertion-vs-type-switches/",
  "publishedAt": "2024-01-31T00:00:00.000Z",
  "site": "at://did:plc:fgtm2c26vfcj74rfmeggbyqj/site.standard.publication/3mnl6f7ob462z",
  "tags": [
    "Go",
    "TIL",
    "Data Structures"
  ],
  "textContent": "Despite moonlighting as a gopher for a while, the syntax for type assertion and type\nswitches still trips me up every time I need to go for one of them.\n\nSo, to avoid digging through the docs or crafting stodgy LLM prompts multiple times, I\ndecided to jot this down in a [Go by Example] style for the next run.\n\nType assertion\n\nType assertion in Go allows you to access an interface variable's underlying concrete type.\nAfter a successful assertion, the variable of interface type is converted to the concrete\ntype to which it's asserted.\n\nThe syntax is i.(T), where i is a variable of interface type and T is the type you are\nasserting.\n\nBasic usage\n\nHere, s gets the type string, and the program outputs Hello.\n\nAsserting primitive types\n\nThis code checks if i is an int and prints its value if so. The value of ok will be\nfalse if i isn't an integer and nothing will be printed to the console.\n\nAsserting composite types\n\nThis will print slice of strings: [apple banana cherry] to the console.\n\nSimilar to primitive types, you can also perform type assertions with composite types. In\nthe example above, we check whether the variable i, which is of an interface type, holds a\nvalue of the type 'slice of strings'.\n\nAsserting other interface types\n\nType assertion can also be used to convert the type of an interface variable to another\ninterface type. Here struct i implements both foo() and bar() methods; satisfying the\nfoobarer interface.\n\nThen in the main function, we check whether i satisfies fooer interface and print a\nmessage if it does. Running this snippet will print i satisfies fooer: &{}.\n\nDynamically checking for certain methods\n\nType assertion can be used to dynamically check if an interface variable implements a\ncertain method. This can come in handy when you want to know if an interface variable has a\ncertain method right before invoking it.\n\nHere, the thing struct implements both foo and bar but the fooer interface only\nneeds the foo() method to be implemented. However, we can check dynamically whether i\nalso implements the bar() method using anonymous interface definition. Running this prints\nthing implements bar method: &{}\n\nHandling failures\n\nWrong assertions, like attempting to convert a string to a float64, cause runtime panics.\n\nType switches\n\nType switches let you compare an interface variable's type against several types. It's\nsimilar to a regular switch statement, but focuses on types.\n\nBasic usage\n\nThis outputs i is an int.\n\nUsing a variable in a type switch case\n\nNotice how we're assinging variable v to i.(type) and then reusing the extracted value\nin the case statements. The snippet converts []byte to a string and prints hello.\n\nHandling multiple types\n\nThe case T1, T2 syntax works like an OR relationship, outputting i is a number.\n\nAddressing composite types\n\nSimilar to primitive types, you can check for composite types in the case statement of a\ntype switch. Here, we're checking whether i is a map[string]bool or not. Running this\nwill output i is a map.\n\nComparing against other interface types\n\nType switches can be also used to compare an interface variable with another interface type.\nThis example is similar to the type assertion one where we're checking whether i satisfies\nfooer, barer or foobarer interface. In this case, i satisfies all three of them but\nthe case statement will stop after the first successful check. So it prints fooer: &{} and\nbails.\n\nDynamically checking for certain methods\n\nSimilar to type assertion, within a type switch, anonymous interface definition can be used\nto dynamically check if an interface variable implements some method.\n\nThe thing struct implements both foo() and bar() methods. However, the fooer\ninterface only requires it to implement foo(). The type switch dynamically checks whether\ni also implements the method bar(). Running this will print\nthing implements bar method: &{}.\n\nSimilarities and differences\n\nSimilarities\n\n- Both handle interfaces and extract their concrete types.\n- They evaluate an interface's dynamic type.\n\nDifferences\n\n- Type assertions check a single type, while type switches handle multiple types.\n- Type assertion uses i.(T), type switch uses a switch statement with literal i.(type).\n- Type assertions can panic or return a success boolean, type switches handle mismatches\n  more gracefully.\n- Type assertions are good when you're sure of the type. Type switches are more versatile\n  for handling various types.\n- Type assertion can get the value and success boolean. Type switches let you access the\n  value in each case block.\n- Type switches can handle multiple types, including a default case, offering more\n  flexibility for various types.\n\nFin!\n\n\n\n\n[go by example]:\n    https://gobyexample.com/",
  "title": "Type assertion vs type switches in Go"
}