# Basics of Variables, Constants, and Data Types in Go

In the previous article, we installed Go on our system and ran our first "Hello, World!" program. Now, in this article, we will learn about variables and data types. This is an important topic because we need to store data in memory while running the code to reuse it throughout the program. To do that in Go, there are some rules. So let's dive deep into this.

## What are Variables in Go?

A variable is a named memory location that stores a value.

In Go, we declare variables using the following syntax or keywords:

* `var` keyword
    
* `:=` → using this syntax for short and fast declaration.
    

### Declaring Variables Using `var`

```go
package main
import "fmt"

func main() {
    var name string = "Rohit Lokhande"
    var age int = 25
    fmt.Println(name, age)
}
```

### Declaring Variable Using Short Declaration Syntax

```go
name := "Rohit"
age := 25
```

`:=` this will automatically infers the type based on the value.

Note `:=` this declaration can only be used inside functions.

## Grouped Variable Declaration

```go
var(
   name="Rohit"
   age = 25
   city = "Pune"
)
```

## Global vs Local Variable

Variables declared outside any function are package-level, which are accessible within the package.

```go
package main
import "fmt"
var global = "I am global"
func main() {
   local := "I am local"
   fmt.Println(global)
   fmt.Println(local)
}
```

## iota keyword

Go uses iota to create enumerated constants easily. It is a keyword in Golang that holds an integer value.

It is typically used within constant declarations to generate a series of related values, incrementing by 1 for each subsequent constant.

```go
const (
   Sunday = iota
   Monday
   Tuesday
   Wednesday
)
fmt.Println(Sunday, Monday, Tuesday) // 0 1 2
```

Every new line with a constant increments iota by 1. This is used widely for status codes, enums etc

### Using `iota` with Expressions

This is also used with expressions to define more complex constant values. Let’s understand with an example. If we want to define constants representing file sizes in bytes, kilobytes, megabytes, and so on, we can achieve this in a simple way using `iota`.

```go
pacakge main
import "fmt"
const (
  _ = iota // Discard the first value (0)
  KB = 1 << (10 * iota) // 1 << (10 * 1)
  MB = 1 << (10 * iota) // 1 << (10 * 2)
  GB = 1 << (10 * iota) // 1 << (10 * 4)
)
func main() {
    fmt.Println("KB:", KB)
    fmt.Println("MB:", MB)
    fmt.Println("GB:", GB)
    fmt.Println("TB:", TB)
}
```

In this, we use bitwise left shifts (&lt;&lt;) in conjunction with iota to calculate the constant values for different file sizes.

## Rules to Remember While Declaring Variable

* All variables must be used otherwise Go will throws a compile-time error.
    
* Variables are block-scoped.
    
* You can declare multiple variable together
    
* ```go
    var x, y = 10,20
    ```
    

## Why does Go require you to use every declared variable?

* **Catches mistakes early**
    
    If you declare a variable but forget to use it, the compiler will let you know right away, preventing a runtime bug from hiding that mistake.
    
* **Encourages clean code**
    
    No unused variables mean the code is easier to read and has fewer maintenance issues.
    
* **Smaller/safer binaries**
    
    Unused imports and values can make builds more complicated or cause unexpected problems. Not allowing them helps keep builds straightforward and predictable.
    

Example for above rule

Broken- compiler error code

```go
package main
func main() {
   var x int // declared but never using
   y := 10   // declared but never used
}
```

Compiler will complain: x declared and not used

Fixed - use the variables

```go
package main

import "fmt"

func main() {
    var x int
    y := 10
    x = y * 2
    fmt.Println(x) // now both x and y are used
}
```

### How to intentionally ignore a value

If you we really want to discard a value, we can use the black identifier `_` . This tells the compiler “I intentionally don’t need this.“

* Ignore a return value:
    
    ```go
    x, _ := someFunc() // ignore second return value
    ```
    
* Mark a value as used (silence unused variable):
    
    ```go
    var x = someFunc()
    _ = x // explicitly mark "x" as used so compiler won't complain
    ```
    

### Best Practices for Unused Compile Time Error

* * If the compiler says "declared and not used," either remove the declaration or actually use the variable.
        
    * While experimenting, `_ = x` is a quick way to silence errors, but prefer to remove dead code before committing.
        
    * For multi-value returns where only some values matter, use `_` for the ones you want to drop.
        
    

## Constants in Go

Constant is an immutable value - once defined, it cannot be changed.

**Declaring Constants**

```go
const PI 3.14
const Greeting = "Hello, Go!"
```

Constants can also be grouped

```go
const (
    StatusOK = 200
    StatusNotFound = 404
)
```

If you try to modify a constant, Go will throw an error:

```go
PI =3.142145 // ❌ compile-time error
```

## Data Types in GO

| **Category** | Types | Example |
| --- | --- | --- |
| Numeric | int, float32,float64,complex64,complex128 | var age int = 5 |
| String | string | var name string = “Rohit” |
| Boolean | bool | var isDev bool = true |
| Derived | array,slice,map,struct,interface | Covered later. |

In this section, we won't dive deep into the differences between `float32`, `float64`, and other numeric types. We will discuss non-primitive data types like arrays and slices later.

## Type inference

Go automatically infers type if not specified

```go
count:= 10 // int
price:=99.99 // float64
message:="Hello" // string
```

### What is Type Inference?

Type inference means Go can automatically determine the data type of a variable based on the value you assign to it, so you don’t have to explicitly write the type every time.

Even though Go is **statically typed**, meaning types are checked at compile time, not runtime, it doesn’t always require you to write them explicitly because the compiler can infer them.

### Rules for Inference

1. Inference happens only during declaration, not late:
    
    ```go
    var x int
    x = 10.5 // Error - 10.5 is float64, not int
    ```
    
2. You can’t mix inferred and explicit types in one declaration
    
    ```go
    var a, b = 1, "hello"   // ✅ both inferred
    var c, d int = 1, "hi"  // ❌ type mismatch for d
    ```
    
3. Inference doesn’t mean dynamic typing
    
    Once inferred, the type is fixed and checked at compile time.
    

## Zero Values for Uninitialized variables

In Go, uninitialized variables are not garbage they take zero values automatically

| Type | Zero Value |
| --- | --- |
| int, float | 0 |
| string | ““ |
| bool | false |
| pointer,slice,map | nill |

## Type Conversion

Go doesn’t support implicit conversions you must convert explicitly

```go
var a int = 10
var b float64 = float64(a)
fmt.Println(b)
```

## Conclusion

Variables, constants, and data types form the foundation of any Go program. Go’s simple but strong type system encourages clean, predictable code, so you always know what’s stored where.

In the next post, we’ll dive into Functions in Go, where you’ll learn how to organize and reuse logic efficiently.
