Given 2 variables (either boolean, integer, int64, TDateTime or string), how can I set A to always point to B?
Let's say A and B are integers, I set B to 10.
From here on I want A to always point to B, so if I do A := 5 it will modify B instead.
I want to be able to do this at runtime.
There are several ways, and all of them are obvious if one understands what a variable is: a pointer to memory.
Using pointers
var
iNumber: Integer; // Our commonly used variables
sText: String;
bFlag: Boolean;
pNumber: PInteger; // Only pointers
pText: PString;
pFlag: PBoolean;
begin
pNumber:= #iNumber; // Set pointers to the same address of the variables
pText:= #sText;
pFlag:= #bFlag;
// Change the memory that both variable and pointer link to. No matter if
// you access it thru the variable or the pointer it will give you the
// same content when accessing it thru the opposite way.
pNumber^:= 1138; // Same as iNumber:= 1138;
sText:= 'Content'; // Same as pText^:= 'Content';
pFlag^:= TRUE; // Same as bFlag:= TRUE;
Using objects
type
TMyVars= class( TObject )
iNumber: Integer;
sText: String;
bFlag: Boolean;
end;
var
oFirst, oSecond: TMyVars;
begin
oFirst:= TMyVars.Create(); // Instanciate object of class
oSecond:= oFirst; // Links to same object
// An object is already "only" a pointer, hence it doesn't matter through
// which variable you access a property, as it will give you always the
// same content/memory.
oFirst.iNumber:= 1138; // Same as oSecond.iNumber:= 1138;
oSecond.sText:= 'Content'; // Same as oFirst.sText:= 'Content';
oFirst.bFlag:= TRUE; // Same as oSecond.bFlag:= TRUE;
Using declarations
var
iNumber: Integer;
sText: String;
bFlag: Boolean;
iSameNumber: Integer absolute iNumber;
iOtherText: String absolute sText;
bSwitch: Boolean absolute bFlag;
begin
// Pascal's keyword "absolute" makes the variable merely an alias of
// another variable, so anything you do with one of both also happens
// with the other side.
iNumber:= 1138; // Same as iSameNumber:= 1138;
sOtherText:= 'Content'; // Same as sText:= 'Content';
bFlag:= TRUE; // Same as bSwitch:= TRUE;
Most commonly pointers are used, but also have the most disadvantages (especially if you're not a disciplined programmer). Since you're using Delphi I recommend using your own classes to then operate on objects of them.
Related
I am a bit confused about passing by reference and value in Go.
I've seen this explained of the * in front of a type.
in front of a type name, means that the declared variable will store an address of another variable of that type (not a value of that
type).
This just doesn't make sense to me.
In Java if I was passing a Database instance into a function I would do
databaseFunction(DatabaseType db) {
// do something
}
However in the go example I have it's passed like so.
func PutTasks(db *sql.DB) echo.HandlerFunc {
}
Why do we need to have the asterisk in front of the type?
According to this cheat sheet, I found.
func PrintPerson(p *Person) ONLY receives the pointer address
(reference)
I don't understand why I would only want to send a pointer address as a parameter.
First, Go technically has only pass-by-value. When passing a pointer to an object, you're passing a pointer by value, not passing an object by reference. The difference is subtle but occasionally relevant. For example, you can overwrite the pointer value which has no impact on the caller, as opposed to dereferencing it and overwriting the memory it points to.
// *int means you *must* pass a *int (pointer to int), NOT just an int!
func someFunc(x *int) {
*x = 2 // Whatever variable caller passed in will now be 2
y := 7
x = &y // has no impact on the caller because we overwrote the pointer value!
}
As to your question "Why do we need to have the asterisk in front of the type?": The asterisk indicates that the value is of type pointer to sql.DB, rather than a value of type sql.DB. These are not interchangeable!
Why would you want to send a pointer address? So that you can share the value between the caller of a function and the function body, with changes made inside the function reflected in the caller (for example, a pointer is the only way that a "setter" method can work on an object). While Java passes objects by reference always, Go passes by value always (i.e. it creates a copy of the value in the function); if you pass something to a function, and that function modifies that value, the caller won't see those changes. If you want changes to propogate outside the function, you must pass a pointer.
See also: the Go tour section on Pointers, the Go spec section on pointers, the Go spec section on the address operators
The purpose of reference semantics is to allow a function to manipulate data outside its own scope. Compare:
func BrokenSwap(a int, b int) {
a, b = b, a
}
func RealSwap(a *int, b *int) {
*a, *b = *b, *a
}
When you call BrokenSwap(x, y), there is no effect, because the function receives and manipulates a private copy of the data. By contrast, when you call RealSwap(&x, &y), you actually exchange the values of the caller's x and y. Taking the address of the variables explicitly at the call site informs the reader that those variables may be mutated.
Pass by Reference :-
When you pass a same variable into a function by different name.
Below example from C++ (as Go doesnt have this concept), where a and a1 are same variable.
void swap(int& a1, int& b1)
{
int tmp = a1;
a1 = b1;
b1 = tmp;
}
int main()
{
int a = 10, b = 20;
swap(a, b);
cout << "a " << a << " b " << b ;
}
Go passes everything as data( means it copies the data from current active frame to new active frame of new function). So if you pass values it copies the value and advantage is safety from accidental modification. And when it passes address of variable its copied also into the new pointer variables but has advantage of efficiency since size of pointer is smaller.
This is pointers to pointers
package main
import "fmt"
func main() {
var num int
fmt.Println(&num) // 0x...0
makePointer(&num)
}
func makePointer(firstPointer *int) {
fmt.Println(firstPointer) // 0x...0
fmt.Println(&firstPointer) // 0x...1
makePointerToAPointer(&firstPointer)
}
func makePointerToAPointer(secondPointer **int) {
fmt.Println(secondPointer) // 0x...1
fmt.Println(&secondPointer) // 0x...2
}
When would you actually use this? You can properly come up with something where it would be easier to do something else, but that is not what I asking about. I really want to know where in production you would use this?
Pointers to pointers make sense in function parameters sometimes; not **int probably, but a pointer to a pointer to some struct, where you want the function to be able to change what object a variable points to, not just to change the contents of the struct. For example, there are a few functions in the internals of the Go compiler that take a **Node (see cmd/compile/internal/gc/racewalk.go).
I've also written a couple of functions myself that take a **html.Node; they operate on an HTML page that may or may not have already been parsed into a tree of *html.Nodes, and they may or may not need to parse the page—but if they do, I want to keep the parsed tree around so that I don't have to parse it again. These are in github.com/andybalholm/redwood/prune.go.
They are much more common in languages that do not have multiple return values, since they can be used as a way to return an additional value that is a pointer. Many Objective-C methods take an NSError** as their last parameter so that they can optionally return an NSError*.
The goal to pass a pointer to something is if there is need to modify the pointed value. (We also use pointers to avoid copying large data structures when passing, but that is just for optimization.)
Like in this example:
func main() {
var i int
fmt.Println(i)
inc(&i)
fmt.Println(i)
}
func inc(i *int) {
*i++
}
Output is the expected (try it on the Go Playground):
0
1
If parameter of inc() would receive an int only, it could only modify the copy and not the original value, and so the caller would not observe the changed value.
Same goes with pointer to pointer to something. We use pointer to pointer to something, if we need to modify the pointed value, that is the pointed pointer. Like in this example:
func main() {
var i *int
fmt.Println(i)
alloc(&i, 1)
fmt.Println(i, *i)
setToNil(&i)
fmt.Println(i)
}
func alloc(i **int, initial int) {
*i = new(int)
**i = initial
}
func setToNil(i **int) {
*i = nil
}
Output (try it on the Go Playground):
<nil>
0x1040a130 1
<nil>
The reason why pointer to pointer is not really used is because modifying a pointed value can be substituted by returning the value, and assigning it at the caller:
func main() {
var i *int
fmt.Println(i)
i = alloc(1)
fmt.Println(i, *i)
i = setToNil()
fmt.Println(i)
}
func alloc(initial int) *int {
i := new(int)
*i = initial
return i
}
func setToNil() *int {
return nil // Nothing to do here, assignment happens at the caller!
}
Output is the same (address might be different) (try it on the Go Playground):
<nil>
0x1040a130 1
<nil>
This variant is easier to read and maintain, so this is clearly the favored and wide-spread alternative to functions having to modify a pointer value.
In languages where functions and methods can only have 1 return value, it usually requires additional "work" if the function also wants to return other values besides the pointer, e.g. a wrapper is to be created to accommodate the multiple return values. But since Go supports multiple return values, need for pointer to pointer basically drops to zero as it can be substituted with returning the pointer that would be set to the pointed pointer; and it does not require additional work and does not make code less readable.
This is a very similar case to the builtin append() function: it appends values to a slice. And since the slice value changes (its length increases, also the pointer in it may also change if a new backing array needs to be allocated), append() returns the new slice value which you need to assign (if you want to keep the new slice).
See this related question where a pointer to pointer is proposed (but also returning a pointer is also viable / preferred): Golang: Can the pointer in a struct pointer method be reassigned to another instance?
In the same way a pointer to a value lets you have many references to the same value for a consistent view of the value when it changes, a pointer to a pointer lets you have many references to the same reference for a consistent view of the pointer when it changes to point to a different location in memory.
I can't say I've ever seen it used in practice in Go that I can think of.
We have written one program by which we try to find an address of a constant. Is it possible to do it like that?
package main
func main() {
const k = 5
address := &k
}
It gives an error, can anyone tell how can we find the address of a constant?
In short: you can't.
The error message says:
cannot take the address of k
There are limitations on the operand of the address operator &. Spec: Address operators:
For an operand x of type T, the address operation &x generates a pointer of type *T to x. The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal. If the evaluation of x would cause a run-time panic, then the evaluation of &x does too.
Constants are not listed as addressable, and things that are not listed in the spec as addressable (quoted above) cannot be the operand of the address operator & (you can't take the address of them).
It is not allowed to take the address of a constant. This is for 2 reasons:
A constant may not have an address at all.
And even if a constant value is stored in memory at runtime, this is to help the runtime to keep constants that: constant. If you could take the address of a constant value, you could assign the address (pointer) to a variable and you could change that (the pointed value, the value of the constant). Robert Griesemer (one of Go's authors) wrote why it's not allowed to take a string literal's address: "If you could take the address of a string constant, you could call a function [that assigns to the pointed value resulting in] possibly strange effects - you certainly wouldn't want the literal string constant to change." (source)
If you need a pointer to a value being equal to that constant, assign it to a variable of which is addressable so you can take its address, e.g.
func main() {
const k = 5
v := k
address := &v // This is allowed
}
But know that in Go numeric constants represent values of arbitrary precision and do not overflow. When you assign the value of a constant to a variable, it may not be possible (e.g. the constant may be greater than the max value of the variable's type you're assigning it to - resulting in compile-time error), or it may not be the same (e.g. in case of floating point constants, it may lose precision).
I often hit this problem when creating large, nested JSON objects during unit tests. I might have a structure where all the fields are pointers to strings/ints:
type Obj struct {
Prop1 *string
Prop2 *int
Status *string
}
and want to write something like:
obj := Obj{
Prop1: &"a string property",
Prop2: &5,
Status: &statuses.Awesome,
}
When I initialise it, but the language doesn't allow this directly. A quick way to bypass this is to define a function that takes a constant and returns its address:
s := func(s string) *string { return &s }
i := func(i int) *int { return &i }
obj := Obj{
Prop1: s("a string property"),
Prop2: i(5),
Status: s(statuses.Awesome)
}
This works due to the fact that when the constant is passed as a parameter to the function, a copy of the constant is made which means the pointer created in the function does not point to the address of the constant, but to the address of its copy, in the same way as when a constant value is assigned to a var. However, using a function to do this makes it more readable/less cumbersome IMO than having to forward declare large blocks of variables.
The AWS SDK uses this technique. I now find myself regularly adding a package to my projects that looks something like:
package ref
import "time"
func Bool(i bool) *bool {
return &i
}
func Int(i int) *int {
return &i
}
func Int64(i int64) *int64 {
return &i
}
func String(i string) *string {
return &i
}
func Duration(i time.Duration) *time.Duration {
return &i
}
func Strings(ss []string) []*string {
r := make([]*string, len(ss))
for i := range ss {
r[i] = &ss[i]
}
return r
}
Which I call in the following way:
func (t: Target) assignString(to string, value string) {
if to == tags.AuthorityId {
t.authorityId = ref.String(value)
}
// ...
}
You can also add a deref package, though I have generally found this to be less useful:
package deref
func String(s *string, d string) string {
if s != nil { return *s }
return d
}
// more derefs here.
EDIT April 2022:
With the release of go 1.18, it's now possible to define a single method to handle all conversions from constants into pointers:
package ref
func Of[E any](e E) *E {
return &e
}
I found another way to deal with this, which is using AWS API:
import "github.com/aws/aws-sdk-go/aws"
type Obj struct {
*int
}
x := aws.Int(16) // return address
obj := Obj{x} // work fine
this method is literally same as the answer above, but you dont have to write the whole functions on your own.
See: https://docs.aws.amazon.com/sdk-for-go/api/aws/
These 3 options could be helpful:
Using a helper function with generics. (Works for both primitive and custom types)
package main
import "fmt"
type Role string
const (
Engineer Role = "ENGINEER"
Architect Role = "ARCHITECT"
)
const (
EngineerStr string = "ENGINEER"
ArchitectStr string = "ARCHITECT"
)
func main() {
fmt.Println(PointerTo(Engineer)) // works for custom types
fmt.Println(PointerTo(EngineerStr)) // works for primitive types
}
func PointerTo[T any](v T) *T {
return &v
}
Try it on playground
Using pointy. (Works only for primitive types)
Using a ToPointer() method. (Works only for custom types)
package main
import "fmt"
type Role string
const (
Engineer Role = "ENGINEER"
Architect Role = "ARCHITECT"
)
func (r Role) ToPointer() *Role {
return &r
}
func main() {
fmt.Println(Engineer.ToPointer())
}
Try it on playground
What the constants section does not make very clear: Constants are, unlike variables, not present in the compiled code or running program. They are untyped and will only be in memory once they are assigned to a variable.
As a result, they seem1 to have infinite precision. If you look at this example, you can see that I can assign the constant to a variable without casting it, and the variable will hold as much of the constants precision as it can.
1 As the spec also points out, integers have at least 256 bits, floats at least 256 bits mantissa and 32 bits exponent, and the compiler will throw an error if its internal constructs cannot accurately store a constant.
I understand that Go doesn't have any constructors and a New func is used in its place, but according to this example.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := File{fd, name, nil, 0}
return &f
}
They always return &f. Why just simply returning File isn't suffice?
Update
I've tried returning the created object for a simple struct and it's fine. So, I wonder if returning an address is a standard way of constructor or something.
Thanks.
As mentioned, yes, the spec allows you to return either values (as non-pointers) or pointers. It's just a decision you have to make.
When to return pointer?
Usually if the value you return is "more useful" as a pointer. When is it more useful?
For example if it has many methods with pointer receiver. Yes, you could store the return value in a variable and so it will be addressable and you can still call its methods that have pointer receivers. But if a pointer is returned right away, you can "chain" method calls. See this example:
type My int
func (m *My) Str() string { return strconv.Itoa(int(*m)) }
func createMy(i int) My { return My(i) }
Now writing:
fmt.Println(createMy(12).Str())
Will result in error: cannot call pointer method on createMy(12)
But if works if you return a pointer:
func createMy(i int) *My { return (*My)(&i) }
Also if you store the returned value in a data structure which is not addressable (map for example), you cannot call methods on values by indexing a map because values of a map are not addressable.
See this example: My.Str() has pointer receiver. So if you try to do this:
m := map[int]My{0: My(12)}
m[0].Str() // Error!
You can't because "cannot take the address of m[0]". But the following works:
m := map[int]*My{}
my := My(12)
m[0] = &my // Store a pointer in the map
m[0].Str() // You can call it, no need to take the address of m[0]
// as it is already a pointer
And another example for pointers being useful is if it is a "big" struct which will be passed around a lot. http.Request is a shining example. It is big, it is usually passed around a lot to other handlers, and it has methods with pointer receiver.
If you return a pointer, that usually suggests that the returned value is better if stored and passed around as a pointer.
Pointer receiver accepts both pointer and value types, as long as it matches the data type.
type User struct {
name string
email string
age int
}
// NewUserV returns value ... ideally for a User we should not be
// returning value
func NewUserV(name, email string, age int) User {
return User{name, email, age}
}
// NewUserP returns pointer ...
func NewUserP(name, email string, age int) *User {
return &User{name, email, age}
}
// ChangeEmail ...
func (u *User) ChangeEmail(newEmail string) {
u.email = newEmail
}
func main() {
// with value type
usr1 := NewUserV("frank", "frank#camero.com", 22)
fmt.Println("Before change: ", usr1)
usr1.ChangeEmail("frank#gmail.com")
fmt.Println("After change: ", usr1)
// with pointer type
usr2 := NewUserP("john", "john#liliput.com", 22)
fmt.Println("Before change: ", usr2)
usr2.ChangeEmail("john#macabre.com")
fmt.Println("After change: ", usr2)
}
In addition to what icza mentioned about the big struct being passed around. Pointer values are a way of saying that pointer semantics are at play and who ever uses the particular type should not make copy of the value which is being shared by the pointer.
If you look at the struct of File or http type, it maintains channels or some other pointer types which is unique to that value. Make a copy of the value (given to you by the pointer) would lead to hard to find bugs since the copied value might end up writing or reading to the pointer types of the original value.
I have a the following code
http://play.golang.org/p/d-bZxL72az
package main
import "fmt"
type Variables struct {
sum uint64
highest uint64
}
type Data struct {
count uint64
mValue map[string]Variables
}
func (v Variables) Add(value Variables) Variables {
v.sum += value.sum
if v.highest == 0 {
v.highest = value.highest
} else if v.highest < value.highest {
v.highest = value.highest
}
return v
}
func (v *Variables) AddPointer(value Variables) {
v.sum += value.sum
if v.highest == 0 {
v.highest = value.highest
} else if v.highest < value.highest {
v.highest = value.highest
}
}
func main() {
var instances [2]Variables
instances[0] = Variables{sum: 5, highest: 3}
instances[1] = Variables{sum: 10, highest: 2}
var d Data
d.mValue = make(map[string]Variables)
for i:= 0; i < len(instances); i++ {
d.mValue["one"] = d.mValue["one"].Add(instances[i])
d.mValue["two"].AddPointer(instances[i])
}
fmt.Println(d.mValue["one"])
fmt.Println(d.mValue["two"])
}
I get the error
# command-line-arguments
/tmp/sandbox209565070/main.go:42: cannot call pointer method on d.mValue["two"]
/tmp/sandbox209565070/main.go:42: cannot take the address of d.mValue["two"]
(I think) I understand the second error cannot take address - because, it is a map, it cannot take the address (is that correct?)
Is it the same reason for the first error as well (cannot call pointer method)?
Is there a way to use pointer methods on structures that are within the maps..
Yes, same reason. In order to call a method with a pointer receiver, you either need to have a pointer in the first place, or you need an addressable value and Go will automatically take the pointer for you.
What you can do, then, is to make mValue a map[string]*Variables instead of a map[string]Variables. Then you will be storing a pointer to an already-allocated, guaranteed-addressable Variables in the map, and you'll be able to call methods on that pointer.
To expand on the previous answer…
In practice, this isn't usually a problem. If the type makes more sense without pointers (e.g. a small struct where value semantics make more sense) then you wouldn't have pointer receivers and the issue wouldn't arise.
If pointer receivers make sense then you should probably be using pointers to the type in most places, such as in maps (as hobbs said) and you wouldn't have methods that took non-pointer arguments or returned non-pointer values (non-pointer receivers could still make sense and would be easy to use). Again, the issue wouldn't arise.
In the first case if you wanted to use a pointer receiver with a non-pointer map entry, you could use a temporary (addressable) variable and reassign it back into the map.
x := d.mValue["two"]
x.AddPointer(instances[i])
// AddPointer uses a pointer receiver; `x` needs to be addressable,
// it will contain a copy of the value from the map and that copy may
// be changed by the method so we need to copy the new version back
// into the map.
d.mValue["two"] = x
In the second case a few issues arise. First, to avoid nil pointers you need to either initialize the map entries or check for nil/existance on map reads (or make make your pointer receiver methods handle nil valued receivers, but that doesn't help for non-pointer receiver methods though). Second, if for some silly reason you have pointers but still have a method that returned a non-pointer you'd have to use a different syntax to assign to the map.
Something like this perhaps:
// Initialize some map entries to avoid nil pointers
d.mValue = map[string]*Variables{
"one": &Variables{},
"two": &Variables{},
}
for i := 0; i < len(instances); i++ {
// Just calling the non-pointer reciever is easy/fine:
d.mValue["one"].Add(instances[i])
// But you can't do this:
//d.mValue["one"] = d.mValue["one"].Add(instances[i])
// cannot use d.mValue["one"].Add(instances[i]) (type Variables) as type *Variables in assignment
*d.mValue["one"] = d.mValue["one"].Add(instances[i])
d.mValue["two"].AddPointer(instances[i])
}