Better ways of passing functions around?

I did some further test, with the script below:

function f1(x::Float64)
	x = x+3.
end 

mutable struct MyType{F<:Function}
	x::Float64
	func::F
	funcs::Array{Function,1}
	sf::Symbol
	
	function MyType{F}(x::Float64) where {F<:Function}
		this = new()
		this.x = x
		this.funcs = Array{Function,1}(undef,1)
		this
	end
end 

function main()
	t1 = MyType{Function}(3.)
	t1.func = f1
	
	for i=1:1000000
		t1.x = t1.func(i*0.1)
	end
end

function main1()
	t1 = MyType{Function}(3.)

	for i=1:1000000
		t1.x = f1(i*0.1)
	end
end

function main2()
	t1 = MyType{Function}(3.)
	f = f1
	
	for i=1:1000000
		t1.x = f(i*0.1)
	end
end

function main3()
	t1 = MyType{Function}(3.)
	t1.sf = :f1
	f = getfield(Main, t1.sf)
	
	for i=1:1000000
		t1.x = f(i*0.1)
	end
end

function main4()
	t1 = MyType{Function}(3.)
	aDict = Dict{String, Function}()
	aDict["f1"] = f1
	f = get(aDict, "f1", 0)
	
	for i=1:1000000
		t1.x = f(i*0.1)
	end
end

function main5()
	t1 = MyType{Function}(3.)
	f = include_string(Main, "f1")
	
	for i=1:1000000
		t1.x = f(i*0.1)
	end
end
	
function main6(ff::Function)
	t1 = MyType{Function}(3.)
	
	for i=1:1000000
		t1.x = ff(i*0.1)
	end
end

function main7()
	t1 = MyType{Function}(3.)
	t1.funcs[1] = f1
	
	for i=1:1000000
		t1.x = t1.funcs[1](i*0.1)
	end
end
julia> using BenchmarkTools

julia> @btime main()
  133.799 ms (4000001 allocations: 61.04 MiB)

julia> @btime main1()
  1.640 ns (0 allocations: 0 bytes)

julia> @btime main2()
  1.640 ns (0 allocations: 0 bytes)

julia> @btime main3()
  133.398 ms (4000001 allocations: 61.04 MiB)

julia> @btime main4()
  134.623 ms (4000005 allocations: 61.04 MiB)

julia> @btime main5()
  136.345 ms (4000002 allocations: 61.04 MiB)

julia> @btime main6(f1)
  1.640 ns (0 allocations: 0 bytes)

julia> @btime main7()
  140.606 ms (4000002 allocations: 61.04 MiB)

So it look only “main6” may be not so prohibitive for passing functions. Are there other options please?