{"id":1059,"date":"2026-08-16T19:37:43","date_gmt":"2026-08-16T19:37:43","guid":{"rendered":"https:\/\/www.devopsschool.com\/tutorials\/?p=1059"},"modified":"2026-08-16T21:45:38","modified_gmt":"2026-08-16T21:45:38","slug":"go-tutorials-generic-programming-and-generic-functions-in-go","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/tutorials\/go-tutorials-generic-programming-and-generic-functions-in-go\/","title":{"rendered":"Go Tutorials &#8211; Generic Programming and Generic Functions in Go"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Part 1 \u2014 One-Page Summary<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">What is Generic Programming?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Generic programming<\/strong> means writing code that can work with <strong>different data types without rewriting the same logic for each type<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Without generics, you might write:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func PrintInt(value int) {\n\tfmt.Println(value)\n}\n\nfunc PrintString(value string) {\n\tfmt.Println(value)\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The logic is identical, but the types are different.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With generics, you can write one function:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func Print&#91;T any](value T) {\n\tfmt.Println(value)\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now it works with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Print(10)\nPrint(\"Hello\")\nPrint(true)\nPrint(3.14)\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">What is a Generic Function?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A <strong>generic function<\/strong> is a function that uses one or more <strong>type parameters<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example syntax:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func FunctionName&#91;T Constraint](value T) {\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>T          = Type parameter\nConstraint = Which types T is allowed to represent\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func Print&#91;T any](value T)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">means:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><code>Print<\/code> can receive a value of any type, and inside this function that type is represented by <code>T<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">One Easy Complete Example<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ Print is a GENERIC function.\n\/\/\n\/\/ &#91;T any]\n\/\/\n\/\/ T   = type parameter\n\/\/\n\/\/ any = constraint\n\/\/\n\/\/ \"any\" means T can represent any type.\n\/\/\n\/\/ value T means:\n\/\/ value will have whatever type T becomes.\nfunc Print&#91;T any](value T) {\n\n\t\/\/ fmt.Println can print the value\n\t\/\/ regardless of whether T is:\n\t\/\/\n\t\/\/ int\n\t\/\/ string\n\t\/\/ bool\n\t\/\/ float64\n\t\/\/ struct\n\t\/\/ etc.\n\tfmt.Println(value)\n}\n\nfunc main() {\n\n\t\/\/ Here Go understands:\n\t\/\/\n\t\/\/ T = int\n\tPrint(100)\n\n\t\/\/ Here:\n\t\/\/\n\t\/\/ T = string\n\tPrint(\"Hello Go\")\n\n\t\/\/ Here:\n\t\/\/\n\t\/\/ T = bool\n\tPrint(true)\n\n\t\/\/ Here:\n\t\/\/\n\t\/\/ T = float64\n\tPrint(10.5)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ 100\n\t\/\/ Hello Go\n\t\/\/ true\n\t\/\/ 10.5\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Easy Mental Model<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Normal function:\n\nfunc Double(value int)\n\nWorks only with:\nint\n\n\nGeneric function:\n\nfunc Something&#91;T ...](value T)\n\nT becomes the required type\nfor that particular call.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Think of <code>T<\/code> as a <strong>type placeholder<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>T = int\nT = string\nT = float64\nT = User\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">depending on how the generic code is used.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 2 \u2014 Generic Programming Using 5W1H<\/h1>\n\n\n\n<h1 class=\"wp-block-heading\">1. WHAT \u2014 What Are Generics?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Generics let functions and types operate on multiple related types while keeping compile-time type checking.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Without generics:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ Same logic for int.\nfunc FirstInt(values &#91;]int) int {\n\treturn values&#91;0]\n}\n\n\/\/ Same logic repeated for string.\nfunc FirstString(values &#91;]string) string {\n\treturn values&#91;0]\n}\n\nfunc main() {}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">With generics:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ T represents the element type.\n\/\/\n\/\/ &#91;]T means:\n\/\/ \"a slice containing values of type T\"\n\/\/\n\/\/ The return type T means:\n\/\/ return one value of the same type.\nfunc First&#91;T any](values &#91;]T) T {\n\n\t\/\/ values&#91;0] has type T,\n\t\/\/ so it can be returned as T.\n\treturn values&#91;0]\n}\n\nfunc main() {\n\n\tnumbers := &#91;]int{10, 20, 30}\n\n\t\/\/ T becomes int.\n\tfirstNumber := First(numbers)\n\n\twords := &#91;]string{\"Go\", \"Java\", \"Rust\"}\n\n\t\/\/ T becomes string.\n\tfirstWord := First(words)\n\n\t_, _ = firstNumber, firstWord\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FirstInt()\nFirstString()\nFirstFloat()\nFirstUser()\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">we can have:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>First&#91;T]()\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">2. WHY \u2014 Why Do We Need Generics?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The main reason is to avoid repeating the same algorithm for different types.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consider:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ Same logic.\nfunc MaxInt(a, b int) int {\n\tif a &gt; b {\n\t\treturn a\n\t}\n\n\treturn b\n}\n\n\/\/ Same logic again.\nfunc MaxFloat(a, b float64) float64 {\n\tif a &gt; b {\n\t\treturn a\n\t}\n\n\treturn b\n}\n\nfunc main() {}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The algorithm is identical:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if a &gt; b\n    return a\n\nreturn b\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Only the types are different.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Generics allow us to describe the permitted numeric types once.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ Number is a generic CONSTRAINT.\n\/\/\n\/\/ It says:\n\/\/\n\/\/ T may have an underlying type of:\n\/\/\n\/\/ int\n\/\/ int64\n\/\/ float32\n\/\/ float64\n\/\/\n\/\/ The | symbol means OR.\n\/\/\n\/\/ ~int means:\n\/\/ int OR a custom defined type\n\/\/ whose underlying type is int.\ntype Number interface {\n\t~int | ~int64 | ~float32 | ~float64\n}\n\n\/\/ T is allowed to be any type\n\/\/ satisfying Number.\nfunc Max&#91;T Number](a, b T) T {\n\n\t\/\/ This is allowed because every type\n\t\/\/ permitted by Number supports &gt;.\n\tif a &gt; b {\n\t\treturn a\n\t}\n\n\treturn b\n}\n\nfunc main() {\n\n\t\/\/ T = int\n\tfmt.Println(Max(10, 20))\n\n\t\/\/ T = float64\n\tfmt.Println(Max(10.5, 7.2))\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ 20\n\t\/\/ 10.5\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Generics are useful when you have:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Same algorithm\n+\nDifferent types\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">3. WHEN \u2014 When Should You Use Generics?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Use generics when the <strong>same logic genuinely works for multiple types<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Good example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ Contains checks whether a slice\n\/\/ contains a target value.\n\/\/\n\/\/ comparable means T supports:\n\/\/\n\/\/ ==\n\/\/ !=\n\/\/\n\/\/ We need == below,\n\/\/ so comparable is the correct constraint.\nfunc Contains&#91;T comparable](\n\tvalues &#91;]T,\n\ttarget T,\n) bool {\n\n\t\/\/ Each item has type T.\n\tfor _, value := range values {\n\n\t\t\/\/ Allowed because T is comparable.\n\t\tif value == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc main() {\n\n\tnumbers := &#91;]int{10, 20, 30}\n\n\tfmt.Println(\n\t\tContains(numbers, 20),\n\t)\n\n\tnames := &#91;]string{\n\t\t\"Alice\",\n\t\t\"Bob\",\n\t}\n\n\tfmt.Println(\n\t\tContains(names, \"Bob\"),\n\t)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ true\n\t\/\/ true\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Good generic use cases include:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Contains\nMin \/ Max\nSorting helpers\nCollection utilities\nReusable data structures\nMap \/ Filter style utilities\nSets\nStacks\nQueues\nCache containers\nAlgorithms working across related types\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do <strong>not<\/strong> use generics just because they exist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func Add(a, b int) int {\n\treturn a + b\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">is perfectly good if your application only needs integers.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">4. WHERE \u2014 Where Are Generics Used?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Generics can appear in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Generic functions\nGeneric structs\/types\nGeneric containers\nGeneric algorithms\nReusable libraries\nUtility packages\nData processing code\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Example: Generic Struct<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ Box can store one value.\n\/\/\n\/\/ T determines what kind of value\n\/\/ this particular Box stores.\ntype Box&#91;T any] struct {\n\n\t\/\/ Value has type T.\n\tValue T\n}\n\nfunc main() {\n\n\t\/\/ T = int\n\tnumberBox := Box&#91;int]{\n\t\tValue: 100,\n\t}\n\n\t\/\/ T = string\n\ttextBox := Box&#91;string]{\n\t\tValue: \"Hello\",\n\t}\n\n\tfmt.Println(numberBox.Value)\n\tfmt.Println(textBox.Value)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ 100\n\t\/\/ Hello\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Box&#91;int]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">and:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Box&#91;string]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">use the same generic structure with different element types.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">5. WHO \u2014 Who Should Use Generics?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Generics are useful for developers building reusable code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For beginners:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>First learn:\nfunctions\nstructs\nmethods\ninterfaces\nslices\nmaps\n\nThen learn:\ngenerics\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Use generics when you find yourself thinking:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"I am writing exactly the same code again,\nonly because the data type changed.\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That is often a strong sign that generics may help.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">6. HOW \u2014 How Do Generic Functions Work?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Now let&#8217;s move from basic to advanced.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 1 \u2014 Basic Generic Function<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ T is our type parameter.\n\/\/\n\/\/ any means T can be any type.\nfunc Show&#91;T any](value T) {\n\n\t\/\/ value has type T.\n\tfmt.Println(value)\n}\n\nfunc main() {\n\n\t\/\/ Go infers T = int.\n\tShow(100)\n\n\t\/\/ Go infers T = string.\n\tShow(\"Hello\")\n\n\t\/\/ Go infers T = bool.\n\tShow(true)\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">General syntax:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func Name&#91;T Constraint](parameter T) {\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 2 \u2014 Returning <code>T<\/code><\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ Identity receives T\n\/\/ and returns the same type T.\nfunc Identity&#91;T any](value T) T {\n\n\treturn value\n}\n\nfunc main() {\n\n\t\/\/ T = string.\n\tname := Identity(\"Alice\")\n\n\t\/\/ name is string.\n\tfmt.Println(name)\n\n\t\/\/ T = int.\n\tnumber := Identity(100)\n\n\t\/\/ number is int.\n\tfmt.Println(number)\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If input is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>string\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">output is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>string\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If input is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">output is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 3 \u2014 Generic Slice Function<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ T represents the element type\n\/\/ contained inside the slice.\nfunc Last&#91;T any](values &#91;]T) T {\n\n\t\/\/ len(values)-1 gives\n\t\/\/ the final slice index.\n\treturn values&#91;len(values)-1]\n}\n\nfunc main() {\n\n\tnumbers := &#91;]int{\n\t\t10,\n\t\t20,\n\t\t30,\n\t}\n\n\t\/\/ T becomes int.\n\tfmt.Println(\n\t\tLast(numbers),\n\t)\n\n\twords := &#91;]string{\n\t\t\"Go\",\n\t\t\"Rust\",\n\t\t\"Java\",\n\t}\n\n\t\/\/ T becomes string.\n\tfmt.Println(\n\t\tLast(words),\n\t)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ 30\n\t\/\/ Java\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 4 \u2014 Why <code>any<\/code> Cannot Do Everything<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A common beginner mistake is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ This does NOT work:\n\/\/\n\/\/ func Add&#91;T any](a, b T) T {\n\/\/     return a + b\n\/\/ }\n\/\/\n\/\/ Why?\n\/\/\n\/\/ any allows EVERY type.\n\/\/\n\/\/ T could therefore be:\n\/\/\n\/\/ string\n\/\/ bool\n\/\/ struct\n\/\/ &#91;]int\n\/\/\n\/\/ Not every possible type supports +.\n\nfunc main() {}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So if you need an operation like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>+\n&gt;\n&lt;\n==\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">you must give Go an appropriate <strong>constraint<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 5 \u2014 Creating a Constraint<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ Number describes the types\n\/\/ our Add function supports.\ntype Number interface {\n\n\t\/\/ T may be:\n\t\/\/\n\t\/\/ int\n\t\/\/ int64\n\t\/\/ float32\n\t\/\/ float64\n\t\/\/\n\t\/\/ including custom types\n\t\/\/ with these underlying types.\n\t~int |\n\t\t~int64 |\n\t\t~float32 |\n\t\t~float64\n}\n\nfunc Add&#91;T Number](a, b T) T {\n\n\t\/\/ + is safe because every type\n\t\/\/ in Number supports addition.\n\treturn a + b\n}\n\nfunc main() {\n\n\tfmt.Println(\n\t\tAdd(10, 20),\n\t)\n\n\tfmt.Println(\n\t\tAdd(2.5, 3.5),\n\t)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ 30\n\t\/\/ 6\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 6 \u2014 Understanding <code>~<\/code><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Consider:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>type UserID int\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>UserID<\/code> is not exactly <code>int<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is its own named type.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>~<\/code> allows it when the underlying type matches.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ UserID is its own type,\n\/\/ but its underlying type is int.\ntype UserID int\n\ntype Integer interface {\n\n\t\/\/ ~int means:\n\t\/\/\n\t\/\/ int\n\t\/\/\n\t\/\/ OR\n\t\/\/\n\t\/\/ any named type whose\n\t\/\/ underlying type is int.\n\t~int\n}\n\nfunc Double&#91;T Integer](value T) T {\n\n\treturn value * 2\n}\n\nfunc main() {\n\n\tvar id UserID = 100\n\n\t\/\/ UserID satisfies ~int.\n\tresult := Double(id)\n\n\tfmt.Println(result)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ 200\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Easy rule:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int\n=\nexact int type\n\n~int\n=\nint and custom types based on int\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 7 \u2014 <code>comparable<\/code><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Go provides the built-in constraint:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>comparable\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Use it when you need:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>==\n!=\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ T must support == and !=.\nfunc Equal&#91;T comparable](a, b T) bool {\n\n\treturn a == b\n}\n\nfunc main() {\n\n\tfmt.Println(\n\t\tEqual(10, 10),\n\t)\n\n\tfmt.Println(\n\t\tEqual(\"Go\", \"Go\"),\n\t)\n\n\tfmt.Println(\n\t\tEqual(\"Go\", \"Rust\"),\n\t)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ true\n\t\/\/ true\n\t\/\/ false\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 8 \u2014 Two Type Parameters<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A generic function can have multiple type parameters.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ K and V are two separate type parameters.\n\/\/\n\/\/ K might be string.\n\/\/\n\/\/ V might be int.\nfunc PrintPair&#91;K any, V any](\n\tkey K,\n\tvalue V,\n) {\n\n\tfmt.Println(key, value)\n}\n\nfunc main() {\n\n\t\/\/ K = string\n\t\/\/ V = int\n\tPrintPair(\n\t\t\"Age\",\n\t\t30,\n\t)\n\n\t\/\/ K = int\n\t\/\/ V = string\n\tPrintPair(\n\t\t1,\n\t\t\"Alice\",\n\t)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ Age 30\n\t\/\/ 1 Alice\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 9 \u2014 Generic Function Returning Different Type<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The output type does not have to be the same as the input type.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n)\n\n\/\/ T = input element type.\n\/\/\n\/\/ R = output element type.\n\/\/\n\/\/ transform receives T\n\/\/ and converts it into R.\nfunc Map&#91;T any, R any](\n\tvalues &#91;]T,\n\ttransform func(T) R,\n) &#91;]R {\n\n\t\/\/ Create result slice\n\t\/\/ with the same length.\n\tresult := make(\n\t\t&#91;]R,\n\t\tlen(values),\n\t)\n\n\tfor i, value := range values {\n\n\t\t\/\/ Convert T into R\n\t\t\/\/ using the supplied function.\n\t\tresult&#91;i] = transform(value)\n\t}\n\n\treturn result\n}\n\nfunc main() {\n\n\tnumbers := &#91;]int{\n\t\t10,\n\t\t20,\n\t\t30,\n\t}\n\n\t\/\/ Input T = int\n\t\/\/\n\t\/\/ Output R = string\n\tresult := Map(\n\t\tnumbers,\n\t\tfunc(number int) string {\n\n\t\t\treturn strconv.Itoa(number)\n\t\t},\n\t)\n\n\tfmt.Println(result)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ &#91;10 20 30]\n\t\/\/\n\t\/\/ These are strings inside &#91;]string.\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is an important real-world generic pattern:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;]T\n \u2193\ntransform\n \u2193\n&#91;]R\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Level 10 \u2014 Generic Struct with Method<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\n\n\/\/ Stack can store values of type T.\ntype Stack&#91;T any] struct {\n\n\titems &#91;]T\n}\n\n\/\/ The method uses the same T\n\/\/ belonging to Stack.\nfunc (s *Stack&#91;T]) Push(value T) {\n\n\t\/\/ Add value to the end.\n\ts.items = append(\n\t\ts.items,\n\t\tvalue,\n\t)\n}\n\n\/\/ Pop returns the last item.\nfunc (s *Stack&#91;T]) Pop() T {\n\n\tlastIndex := len(s.items) - 1\n\n\tvalue := s.items&#91;lastIndex]\n\n\ts.items = s.items&#91;:lastIndex]\n\n\treturn value\n}\n\nfunc main() {\n\n\t\/\/ Stack storing integers.\n\tnumbers := Stack&#91;int]{}\n\n\tnumbers.Push(10)\n\tnumbers.Push(20)\n\n\tfmt.Println(\n\t\tnumbers.Pop(),\n\t)\n\n\t\/\/ Stack storing strings.\n\twords := Stack&#91;string]{}\n\n\twords.Push(\"Go\")\n\twords.Push(\"Rust\")\n\n\tfmt.Println(\n\t\twords.Pop(),\n\t)\n\n\t\/\/ Output:\n\t\/\/\n\t\/\/ 20\n\t\/\/ Rust\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is one of the strongest use cases for generic programming:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Stack&#91;int]\nStack&#91;string]\nStack&#91;User]\nStack&#91;Order]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">without writing four different Stack implementations.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Practical Use Cases<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Use Case 1 \u2014 Contains<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>func Contains&#91;T comparable](\n\tvalues &#91;]T,\n\ttarget T,\n) bool {\n\n\tfor _, value := range values {\n\t\tif value == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Useful for:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;]int\n&#91;]string\n&#91;]UserID\nother comparable values\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Use Case 2 \u2014 Generic Set<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ Set uses T as a map key.\n\/\/\n\/\/ Map keys must be comparable,\n\/\/ therefore T must be comparable.\ntype Set&#91;T comparable] map&#91;T]struct{}\n\nfunc (s Set&#91;T]) Add(value T) {\n\n\ts&#91;value] = struct{}{}\n}\n\nfunc (s Set&#91;T]) Contains(value T) bool {\n\n\t_, exists := s&#91;value]\n\n\treturn exists\n}\n\nfunc main() {\n\n\tnumbers := Set&#91;int]{}\n\n\tnumbers.Add(10)\n\tnumbers.Add(20)\n\n\t_ = numbers.Contains(10)\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Use Case 3 \u2014 Reusable Data Container<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ Result can contain different\n\/\/ types of successful values.\ntype Result&#91;T any] struct {\n\n\tValue T\n\n\tErr error\n}\n\nfunc main() {\n\n\t\/\/ Result containing string.\n\tstringResult := Result&#91;string]{\n\t\tValue: \"Success\",\n\t\tErr:   nil,\n\t}\n\n\t\/\/ Result containing int.\n\tnumberResult := Result&#91;int]{\n\t\tValue: 100,\n\t\tErr:   nil,\n\t}\n\n\t_, _ = stringResult, numberResult\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Generics vs <code>any<\/code><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Do not confuse these two.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ Using any:\n\/\/\n\/\/ Input loses its specific static relationship\n\/\/ inside the API.\nfunc PrintAny(value any) {\n\t_ = value\n}\n\n\/\/ Using generic T:\n\/\/\n\/\/ T preserves the concrete type relationship.\nfunc Identity&#91;T any](value T) T {\n\n\treturn value\n}\n\nfunc main() {\n\n\t\/\/ Generic version knows:\n\t\/\/\n\t\/\/ input  = string\n\t\/\/ output = string\n\tname := Identity(\"Alice\")\n\n\t_ = name\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Think:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>any\n===\n\"I accept any value.\"\n\n\nT\n=\n\"I work with a specific type,\nbut that type is chosen when\nthe generic code is used.\"\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Generics vs Interfaces<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ Interface:\n\/\/\n\/\/ Used when the important question is:\n\/\/\n\/\/ \"What can this value DO?\"\ntype Saver interface {\n\tSave() error\n}\n\n\/\/ Generic:\n\/\/\n\/\/ Used when the important question is:\n\/\/\n\/\/ \"Can the SAME algorithm work\n\/\/ with different types?\"\nfunc First&#91;T any](values &#91;]T) T {\n\n\treturn values&#91;0]\n}\n\nfunc main() {}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Easy distinction:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>INTERFACE\n---------\nBehavior\n\n\"What methods do you have?\"\n\n\nGENERICS\n--------\nReusable typed algorithm\n\n\"What type are we working with?\"\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">When NOT to Use Generics<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ This is perfectly clear.\n\/\/\n\/\/ If your application only needs int,\n\/\/ generics add no real benefit.\nfunc Add(a, b int) int {\n\n\treturn a + b\n}\n\nfunc main() {}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Don&#8217;t change simple code into:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func Add&#91;T SomeHugeConstraint](a, b T) T\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">unless multiple types are actually needed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use generics when they:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Reduce real duplication\nImprove reusable libraries\nKeep type safety\nMake algorithms\/data structures reusable\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Avoid them when they:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Make simple code harder to read\nAdd unnecessary constraints\nSolve a problem you don't actually have\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Final 5W1H Cheat Sheet<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ WHAT?\n\/\/\n\/\/ Generics allow code to work\n\/\/ with multiple types.\n\n\/\/ ---------------------------------\n\n\/\/ WHY?\n\/\/\n\/\/ Avoid repeating the same algorithm\n\/\/ for int, string, float, User, etc.\n\n\/\/ ---------------------------------\n\n\/\/ WHEN?\n\/\/\n\/\/ When the same logic genuinely works\n\/\/ for multiple types.\n\n\/\/ ---------------------------------\n\n\/\/ WHERE?\n\/\/\n\/\/ Functions\n\/\/ structs\n\/\/ containers\n\/\/ algorithms\n\/\/ libraries\n\/\/ utility code\n\n\/\/ ---------------------------------\n\n\/\/ WHO?\n\/\/\n\/\/ Developers building reusable,\n\/\/ type-safe code.\n\n\/\/ ---------------------------------\n\n\/\/ HOW?\n\/\/\n\/\/ Declare a type parameter:\n\/\/\n\/\/ &#91;T Constraint]\n\nfunc Identity&#91;T any](value T) T {\n\n\treturn value\n}\n\nfunc main() {\n\n\t_ = Identity(100)\n\n\t_ = Identity(\"Go\")\n}\n<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">The 6 Things to Remember<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\n\/\/ 1.\n\/\/\n\/\/ T is a type parameter.\n\/\/\n\/\/ Think:\n\/\/ \"placeholder for a type.\"\n\n\/\/ ---------------------------------\n\n\/\/ 2.\n\/\/\n\/\/ any means T can be any type.\n\nfunc Show&#91;T any](value T) {\n\t_ = value\n}\n\n\/\/ ---------------------------------\n\n\/\/ 3.\n\/\/\n\/\/ comparable means T supports:\n\/\/\n\/\/ ==\n\/\/ !=\n\nfunc Equal&#91;T comparable](a, b T) bool {\n\treturn a == b\n}\n\n\/\/ ---------------------------------\n\n\/\/ 4.\n\/\/\n\/\/ Custom constraints can restrict T.\n\ntype Number interface {\n\t~int | ~float64\n}\n\nfunc Add&#91;T Number](a, b T) T {\n\treturn a + b\n}\n\n\/\/ ---------------------------------\n\n\/\/ 5.\n\/\/\n\/\/ Multiple type parameters are possible.\n\nfunc Pair&#91;A any, B any](a A, b B) {\n\t_, _ = a, b\n}\n\n\/\/ ---------------------------------\n\n\/\/ 6.\n\/\/\n\/\/ Use generics when the SAME LOGIC\n\/\/ should work safely with DIFFERENT TYPES.\n\nfunc main() {}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">One Sentence to Remember<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ GENERIC PROGRAMMING:\n\/\/\n\/\/ \"Write the algorithm once,\n\/\/ allow the type to vary,\n\/\/ while keeping compile-time type safety.\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And a <strong>generic function<\/strong> is simply:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ A function containing one or more\n\/\/ type parameters such as T.\n\nfunc Example&#91;T any](value T) T {\n\treturn value\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The easiest mental model is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>T = a blank space for a TYPE.\n\nCall:\n\nIdentity(100)\n\nT becomes:\n\nint\n\n\nCall:\n\nIdentity(\"Go\")\n\nT becomes:\n\nstring\n\n\nSame function.\nDifferent types.\nNo duplicated logic.\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Part 1 \u2014 One-Page Summary What is Generic Programming? Generic programming means writing code that can work with different data types without rewriting the same logic for&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1059","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1059","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/comments?post=1059"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1059\/revisions"}],"predecessor-version":[{"id":1072,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1059\/revisions\/1072"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/media?parent=1059"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/categories?post=1059"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/tags?post=1059"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}