Question

Create a *int64 Value in Go: Pointers, Literals, and Addressability

gopointersstructliterals

Question

Given a Go struct with an *int64 field, how can you initialize that field with a pointer to the value 0 in a struct literal?

type SomeType struct {
    SomeField *int64
}

instance := SomeType{
    SomeField: &0, // does not compile
}

Using a conversion also does not compile:

instance := SomeType{
    SomeField: &int64(0), // cannot take the address of int64(0)
}

Why do these expressions fail, and what valid Go syntax can create a *int64 whose pointed-to value is 0?

Short Answer

You will learn that pointers in Go must point to addressable storage, while numeric literals and conversion results are temporary values with no address you can take. You will also see the idiomatic ways to initialize *int64 fields, including new(int64), a local variable, a small pointer helper, and a literal-only composite-literal technique.

Concept

Go's address-of operator, &, creates a pointer to an addressable value. An addressable value is one that occupies a stable, named or otherwise addressable location in memory.

A variable is addressable:

var count int64 = 0
p := &count // p has type *int64

A numeric literal such as 0 is not addressable. It is a value written directly in source code, not a variable with storage that Go lets you refer to. Therefore, this is invalid:

p := &0 // invalid: cannot take the address of 0

Likewise, int64(0) is a conversion expression that produces an int64 value, but that result is not an addressable variable:

p := &int64(0) // invalid: cannot take the address of int64(0)

This rule protects Go's pointer model: a pointer must refer to a real value whose lifetime can safely extend beyond the expression that created it.

For a pointer to the zero value of int64, use new(int64). It allocates an int64, initializes it to zero, and returns *int64:

instance := SomeType{
    SomeField: new(int64),
}

This distinction matters whenever pointers express optional values. A nil *int64 often means “not provided,” while a non-nil pointer to 0 means “explicitly provided as zero.”

Mental Model

Think of a pointer as a street address.

  • A variable is a real house with an address: &count is valid.
  • The literal 0 is an instruction saying “use zero,” like writing a number on a note. It is not a house, so it has no street address.
  • int64(0) changes the kind of number on the note, but it still does not create a house.
  • new(int64) creates a new house containing the default value 0 and gives you its address.

Go permits pointers only to things that can reliably have an address.

Take Quiz

Syntax and Examples

The field type determines the pointer type you need:

type SomeType struct {
    SomeField *int64
}

SomeField needs a value of type *int64, not int and not int64.

Use new for a pointer to zero

instance := SomeType{
    SomeField: new(int64),
}

fmt.Println(*instance.SomeField) // 0

new(int64) returns *int64. The allocated int64 starts at its zero value, which is 0.

Use a variable when you have a specific value

value := int64(42)
instance := SomeType{
    SomeField: &value,
}

fmt.Println(*instance.SomeField) // 42

The variable value is addressable, so &value is valid.

Use a reusable helper for values other than zero

func Int64Ptr(v int64) *int64 {
    return &v
}

instance := SomeType{
    SomeField: Int64Ptr(42),
}

Returning &v is safe. Go's compiler ensures the value remains valid after the function returns when its address escapes.

Literal-only expression: possible, but usually not preferred

If an expression must appear inline and you do not want a named helper, index an array literal:

instance := SomeType{
    SomeField: &[]int64{0}[0],
}

The array/slice element is addressable, so this produces *int64. Although valid, it is less readable than new(int64) for zero or Int64Ptr(42) for another value.

Note: &0 is invalid for both *int and *int64. An untyped numeric literal does not become addressable merely because a pointer type is expected.

Step by Step Execution

Consider this code:

type SomeType struct {
    SomeField *int64
}

func main() {
    instance := SomeType{
        SomeField: new(int64),
    }

    *instance.SomeField = 7
}

Step by step:

  1. SomeField is declared as *int64, so it must hold an address of an int64 value or nil.
  2. new(int64) creates storage for one int64 value.
  3. Go initializes that storage to the int64 zero value: 0.
  4. new(int64) returns the address of that storage, with type *int64.
  5. The struct field receives that pointer.
  6. *instance.SomeField dereferences the pointer and accesses the actual int64 value.
  7. The assignment changes the pointed-to value from 0 to 7.

By contrast, &int64(0) fails before the program runs: int64(0) is a temporary expression result, not an addressable location.

Real World Use Cases

Pointers to numeric values are useful when zero and absence mean different things.

  • HTTP API request payloads: nil can mean “do not change this field,” while Int64Ptr(0) can mean “set it to zero.”
  • Database updates: a NULL database value may map to nil, while a real database value of 0 maps to a non-nil pointer.
  • Configuration: nil may mean “use the default timeout,” while a pointer to 0 may mean “disable the timeout.”
  • JSON serialization: with tags such as omitempty, a non-nil *int64 whose value is 0 can be included, while a nil pointer can be omitted.
  • Generated API clients: OpenAPI and protobuf-related code frequently uses pointer fields to represent optional scalar values.

Example of preserving this distinction:

type UpdateRequest struct {
    RetryLimit *int64
}

func Int64Ptr(v int64) *int64 { return &v }

noChange := UpdateRequest{
    RetryLimit: nil,
}

setToZero := UpdateRequest{
    RetryLimit: Int64Ptr(0),
}

_ = noChange
_ = setToZero
Take Quiz

Real Codebase Usage

In production Go code, choose the clearest approach for the value you need.

Use new(T) for the zero value

settings := SomeType{SomeField: new(int64)}

This is concise and clearly communicates “a non-nil pointer to zero.”

Use a typed pointer helper for explicit values

func Int64Ptr(v int64) *int64 { return &v }

settings := SomeType{SomeField: Int64Ptr(30)}

Projects often collect helpers like StringPtr, BoolPtr, and Int64Ptr in a small package. In Go 1.18 and later, a generic helper can serve all types:

func Ptr[T any](v T) *T { return &v }

settings := SomeType{SomeField: Ptr(int64(30))}

Validate pointers with guard clauses

Before dereferencing a pointer, check whether it is nil when nil is allowed:

func retryLimit(input *int64) int64 {
    if input == nil {
        return 3
    }
    return *input
}

This prevents a runtime panic from dereferencing nil.

Avoid shared mutable pointer values accidentally

If multiple structs use the same pointer, modifying one affects what the others observe:

value := int64(0)
a := SomeType{SomeField: &value}
b := SomeType{SomeField: &value}

*a.SomeField = 9
fmt.Println(*b.SomeField) // 9

Create separate pointers when each struct must own an independent value.

Common Mistakes

Taking the address of a literal

p := &0

This does not compile because literals are not addressable. Use a variable, new(int64) for zero, or a pointer helper.

Taking the address of a conversion result

p := &int64(0)

This also does not compile. The conversion produces a value, not an addressable variable.

Using the wrong integer type

instance := SomeType{
    SomeField: new(int), // invalid: *int is not *int64
}

Pointer types must match exactly. *int, *int32, and *int64 are distinct types.

Use:

instance := SomeType{
    SomeField: new(int64),
}

Confusing nil with a pointer to zero

instance := SomeType{SomeField: nil}

This is valid, but it does not point to 0. Dereferencing it panics:

fmt.Println(*instance.SomeField) // panic if SomeField is nil

Use new(int64) when a non-nil pointer to zero is required.

Taking the address of a map element

values := map[string]int64{"limit": 0}
p := &values["limit"] // invalid

Map elements are not addressable because the map may move or replace their storage internally. Copy the value to a variable first:

value := values["limit"]
p := &value

Reusing one pointer unintentionally

A pointer shares one underlying value. If independent values are required, make a new variable or call the helper separately for each field.

Comparisons

Expression or approachResultWhen to use
nilA nil *int64The value is absent or unspecified.
new(int64)A non-nil *int64 pointing to 0You specifically need a pointer to the zero value.
&value where value is int64A pointer to an existing variableThe value already exists or needs a meaningful name.
Int64Ptr(42)A *int64 pointing to 42Clean, reusable inline initialization.
Ptr(int64(42))A *int64 pointing to 42Generic helper in Go 1.18+.
&[]int64{42}[0]A *int64 pointing to 42Valid inline syntax, but usually less readable.
&0Compile errorLiterals are not addressable.
&int64(0)Compile errorConversion results are not addressable.

new(int64) and Int64Ptr(0) both create a non-nil pointer to zero. The main difference is intent: new(int64) is ideal for zero, while Int64Ptr(v) reads naturally when the value is explicit.

Take Quiz

Cheat Sheet

// Field requiring a pointer to int64
type SomeType struct {
    SomeField *int64
}

// Non-nil pointer to int64 zero
x := SomeType{SomeField: new(int64)}

// Pointer through an addressable variable
v := int64(42)
x = SomeType{SomeField: &v}

// Reusable helper
func Int64Ptr(v int64) *int64 { return &v }
x = SomeType{SomeField: Int64Ptr(42)}

// Generic helper (Go 1.18+)
func Ptr[T any](v T) *T { return &v }
x = SomeType{SomeField: Ptr(int64(42))}

// Valid but less idiomatic literal-only form
x = SomeType{SomeField: &[]int64{42}[0]}

Rules:

  • & requires an addressable operand.
  • Variables and array/slice elements are addressable.
  • Numeric literals, conversion results, and map elements are not addressable.
  • *int and *int64 are different, incompatible types.
  • nil is not the same as a pointer to 0.
  • Check a pointer for nil before dereferencing it when nil is possible.

FAQ

Why does &int64(0) not compile in Go?

int64(0) is a conversion expression that produces a temporary value. Go permits & only on addressable values, such as variables and array or slice elements.

Does &0 work for *int in Go?

No. 0 is a numeric literal and is not addressable, regardless of whether the desired type is *int, *int64, or another pointer type.

What is the shortest way to create a *int64 pointing to zero?

Use new(int64):

p := new(int64)

It returns a non-nil *int64 whose value is 0.

Is returning &v from func Int64Ptr(v int64) *int64 safe?

Yes. Go ensures that v remains allocated for as long as the returned pointer can be used. You do not get a dangling pointer.

Can I use new(int64) for a value other than zero?

Yes, but assign through the returned pointer afterward:

p := new(int64)
*p = 42

For inline nonzero values, a helper such as Int64Ptr(42) is usually clearer.

What does nil mean for an *int64 field?

It means the field does not point to any int64 value. Whether that represents “missing,” “unknown,” or “use a default” depends on your program's design.

Why is &[]int64{0}[0] valid?

The indexing expression refers to an element in a newly created slice backing array. That element is addressable, unlike the standalone literal 0. It is legal but generally less readable than new(int64) or a helper function.

Take Quiz

Mini Project

Description

Build a configuration constructor for a worker service. The configuration uses *int64 so it can distinguish an omitted retry limit from an explicitly configured retry limit of 0. This models a common API and configuration pattern.

Goal

Create configurations that represent default behavior, an explicitly disabled retry limit, and a custom retry limit without unsafe pointer handling.

Requirements

Use a struct with an *int64 retry-limit field. Create one configuration where the retry limit is omitted (nil). Create one configuration where the retry limit is explicitly 0. Create one configuration where the retry limit is 5. Write a function that resolves nil to a default value and safely dereferences non-nil values.

Take Quiz

Keep learning

Related questions

View more