
In Go, you can't have a traditional constructor like in other languages, but you can achieve similar functionality with initialization techniques.
Go's lack of constructors is due to its simplicity and focus on explicit initialization.
One common technique is using the New function, which returns a pointer to a new instance of a type.
This approach is seen in the example of the String type, where the New function is used to create a new string instance.
Here's an interesting read: Go vs Golang
Initialization and Creation
Initialization in Go is more powerful than in C or C++ and can handle complex structures correctly. This power allows for arbitrary values to format themselves automatically for printing.
The ability to attach a method like String to any user-defined type makes it possible for values to format themselves automatically. This technique is useful for scalar types like floating-point types, such as ByteSize.
A composite literal creates a new instance each time it is evaluated, and its fields can be laid out in any order. The missing ones left as their respective zero values.
Here are the differences between new and make:
The built-in function make(T, args) serves a purpose different from new(T) and creates slices, maps, and channels only. It returns an initialized value of type T (not *T).
A different take: T Golang
Composite Literals
Composite literals are a powerful tool for simplifying initialization in Go. They create a new instance each time they are evaluated, which is different from C.
You can return the address of a local variable without worrying about its storage disappearing after the function returns. This means you can take the address of a composite literal to allocate a fresh instance each time it's evaluated.
The fields of a composite literal must be laid out in order and all present, but you can label them explicitly as field:value pairs to make the initializers appear in any order. Missing fields will be their respective zero values.
If a composite literal contains no fields at all, it creates a zero value for the type. This means new(File) and &File{} are equivalent.
Composite literals can be created for arrays, slices, and maps, with the field labels being indices or map keys as appropriate.
Allocation with Make
Allocation with make is used to create slices, maps, and channels, which are references to data structures that must be initialized before use.
These types, such as slices, have internal data structures that must be set up before they can be used.
Make initializes the internal data structure and prepares the value for use, unlike new which returns a pointer to a newly allocated, zeroed slice structure.
For example, make([]int, 100) allocates an array of 100 ints, and make([]int, 10, 100) creates a slice structure with length 10 and a capacity of 100 pointing at the first 10 elements of the array.
The capacity can be omitted when making a slice, but it's good to know that make returns an initialized value of type T, not *T.
Remember, make only applies to maps, slices, and channels, and does not return a pointer.
Suggestion: Golang Use .env File
Initialization
Initialization in Go is more powerful than in C or C++ due to its ability to build complex structures during initialization.

The ordering issues among initialized objects, even among different packages, are handled correctly in Go.
You can attach a method like String to any user-defined type, making it possible for arbitrary values to format themselves automatically for printing.
This technique is useful for scalar types like floating-point types, as seen in the example of ByteSize, which prints as 1.00YB.
The use of Sprintf to implement ByteSize's String method is safe because it calls Sprintf with %f, which is not a string format, avoiding recurring indefinitely.
Multiple constructors with different initial values can be achieved by using one constructor with multiple optional parameters or multiple constructors with different parameters.
The bytes package demonstrates this by providing multiple constructors with different initial values.
Constructors are not always necessary, and a zero value can be sufficient, but sometimes an initializing constructor is needed, as seen in the example from the package os.
Composite literals can simplify the initialization process by creating a new instance each time they are evaluated, making it possible to return the address of a local variable.
Expand your knowledge: Create a Package in Golang
The fields of a composite literal must all be present, but by labeling the elements explicitly as field:value pairs, the initializers can appear in any order, with the missing ones left as their respective zero values.
A composite literal with no fields creates a zero value for the type, and expressions like new(File) and &File{} are equivalent.
Using Anonymous Struct Field
Using an anonymous struct field is a clever way to create new structs by inheriting attributes from existing ones. This method is demonstrated in a code example where a ChildWithAge struct is created with an anonymous Child field.
To use an anonymous struct field, you need to create a package main and declare the fmt package, which is used for formatting input and output. This is shown in Step 1 of the example.
The Child struct is created with only one field, Name, in Step 2. In contrast, the ChildWithAge struct has two fields: Age and an anonymous Person field, which is actually a Child field.
Here's an interesting read: Install Golang Package
A function called NewChild is created to initialize the Child struct's Name field with a given name, as shown in Step 4. This function is used in Step 7 to initialize the ChildWithAge struct's anonymous Person field.
Here's a step-by-step breakdown of the process:
- Create a package main and declare the fmt package.
- Make a Child structure with only the Name field.
- Make a ChildWithAge struct with an anonymous Person field.
- Create a function called NewChild to initialize the Child struct.
- Create a function called NewChildWithAge to initialize the ChildWithAge struct.
- Use the NewChild function to initialize the ChildWithAge struct's anonymous Person field.
- Set the input age in the ChildWithAge struct's Age field.
By following these steps, you can create a new struct with inherited attributes using an anonymous struct field.
Here's an interesting read: Golang Copy Struct
Initialization Techniques
Initialization in Go is more powerful than in C or C++, allowing complex structures to be built during initialization and handling ordering issues correctly among initialized objects, even among different packages.
The ability to attach a method such as String to any user-defined type makes it possible for arbitrary values to format themselves automatically for printing, as seen in the example of attaching a String method to a ByteSize type.
This technique is useful for scalar types such as floating-point types like ByteSize, which can print in a user-friendly format like 1.00YB when using the YB unit.
The use of Sprintf to implement ByteSize's String method is safe because it calls Sprintf with %f, which is not a string format, avoiding recurring indefinitely.
Go allows multiple constructors with different initial values, which can be achieved either by using one constructor with multiple optional parameters or by using multiple constructors with different parameters.
The bytes package uses multiple constructors with different parameters to construct types based on different initial contents, providing flexibility in initializing types.
Intriguing read: How to Update a Github Using Golang
Type Protection and Encapsulation
Type protection and encapsulation are essential concepts in Go programming.
Declaring a type as private can prevent users from directly modifying it.
The md5 package is a great example of this, where the type is private and can only be interacted with through its interface methods.
Using an interface type as the return type of a constructor function is crucial for type protection.
This approach ensures that users can't directly change public fields of the struct, even if the type itself is private.
Related reading: Check Type of Interface Golang
Function Behavior and Return Types
The -propagateInitFuncReturns option allows you to propagate the returned values from the -init function, which is useful when you need to handle errors or returned values.
You can use this option to generate Go code that returns the constructed value and an error from a validation function, as shown in the example where the NewStruct() constructor returns the constructed value and an error from the validate() function.
In Go, you can also use a function that returns a desired type to construct a new struct, as demonstrated by the NewChildWithAge function that sets the age and returns the finished Child struct.
Discover more: Golang Use Cases
Function returning desired type
Function returning desired type can be a powerful tool in software development. By using a function to return a desired type, you can encapsulate your data and control how it's used.
This approach is crucial when working with private types, as shown in the example from the md5 package. The constructor function returns an interface type, forcing users to work with the type through the interface methods.
Using a function to return a desired type can also simplify the process of constructing new objects. For instance, the NewChildWithAge function in the example sets the age and returns the finished struct, making it easier to create new Child structs.
This approach can also help prevent users from directly modifying private types, which is essential for maintaining the integrity of your code.
A fresh viewpoint: Golang Function Type
Pros and Cons
Instantiating a structure field by field makes more explicit how the different values are used and how variables mix and match with each other.
This approach can be beneficial because it eliminates the "magic" of implicit value assignments, making everything explicit and transparent.
However, this method doesn't prevent users from not setting a value or setting it to nil, which can lead to unexpected behavior.
Using a constructor forces the user to provide all necessary values, ensuring that the function compiles without errors.
But, it's still possible to provide zero values for some fields, so validation is necessary to catch any issues.
Fortunately, constructors can validate their arguments and return a sensible error if something goes wrong, making them a more robust option.
By using a constructor, you can also provide a more ergonomic interface and manipulate internal arguments in a way that would be impossible otherwise.
A different take: Golang Args
Algorithm and Implementation

In Go, a constructor is a function that returns a new instance of a type. The algorithm for creating a constructor in Go involves several steps.
To create a package main, you need to declare the fmt package, which helps with formatting input and output.
A Child struct is constructed with properties Name and Age.
The NewChild function initializes the Name field of the Child struct to the input name and the Age field to 0.
The NewChildWithAge function initializes the Name field to the input name and the Age field to the input age.
Here's a step-by-step breakdown of the process:
- Create a package main and declare the fmt package.
- Construct a Child struct with properties Name and Age.
- Make a function called NewChild that initializes the Name field to the input name and the Age field to 0.
- Make a function called NewChildWithAge that initializes the Name field to the input name and the Age field to the input age.
- Call the NewChild function to create a new Child struct in the NewChildWithAge function.
- Set the age input to the Age field of the Child struct returned by NewChild.
- Return the Child struct back.
The NewChildWithAge function is then called in the main function, passing the parameters "Virat" and 10 as input.
The resulting Child struct is saved in a variable named c.
The Child struct's Name and Age fields are printed using the fmt.Println() function.
Featured Images: pexels.com


