Перевод кода с Java на Golang автоматически. (Полагаю это составила БЯМ)
Добавлено: 17.06.2023 17:28:53
После нескольких месяцев перехода в разработке от Java на Golang, мне показалось, что интересно было бы написать программу, которая должна переводить код программы с Java на Golang автоматически так как синтаксис у обоих языков несколько похож.
Нижеприведенные примеры показывают, что удалось сделать на данный момент.
Работа это даже не прототип, а скорее указывает возможность достижения результата. Для чего я сознательно упрощаю контекст разработки Converter-a где это будет возможно.
Сначала мне показалось важным, что между Java и Go есть разница между реализацией Dynamic Dispatching, точнее в Go Dynamic Dispatching отсутствует.
Отсутствие Dynamic Dispatching в Go пока заставляет меня сделать (недостаток опыта в Go)текущее решение задачи несколько безобразно. Но вариант выгдядет вполне работающим. Скорее всего, авторы Go решают стандартные задачи OO другим путем.
Далее я буду приводить код на Java, за ним следует автоматически сгенерированный код на Golang и комментарии по-необходимости.
1. Начал я конечно с самой популярной программы: "Hello World".
Converter выдал:
2. Далее было интересно справиться с задачей простого наследования.
Converter выдал:
3. В следующем примере надо корректно определить общий для дерева наследования interface.
Converter выдал:
4. Теперь об отсутствии Dynamic Dispatching.
Проблемным методом в последнем примере является amount() в классе Repeater.
Без переписывания кода, я думаю, было бы невозможно вызвать его правильно.
Converter выдал:
5. Обработка Исключений.
Converter выдал:
6. Многопоточность.
Нашел у Oracle простой пример с чудным названием BadThreads там:
https://docs.oracle.com/javase/tutor...questions.html, еще более упростил его, обозвал пример новым простым именем One и дополнил Converter, что бы перевести код на Golang.
В go нет похожей обработки для InterruptedException поэтому Converter не переводит обработку данного прерывания никак.
Converter выдал:
В Go многопоточность одна из главных возможностей, соответcтвенно умение преобразования Java кода с использованием многопоточности в код на Go автоматически, который использует channels, очень важен.
Нашел у Oracle подходящий пример ProducerConsumerExample там:
ProducerConsumerExample, где класс Drop - кандидат на преобразование в Go с использованием channels.
Но, сейчас привожу промежуточный результат без channels.
Еще, прочитал мнение, что преобразование Java кода где используются аннотации в runtime-е -невозможен. Надо исследовать проблему и попытаться понять возможно ли ее как-то решить. Прежде чем переводить проект из статуса "возможность достижения" в статус "прототип" надо посмотреть, что можно сделать с указанными проблемами применительно к аннотациям.
Код на Java:
Converter выдал:
7. Channels. Добрались и до них.
Теперь converter может преобразовывать Java классы в Go channels где это возможно. Предыдущий пример содержит класс Drop, котрый соответствует критериям преобразования, что и показывает нижеприведенный код примера на Go. Соответственно, если converter "не найдет" класс подходящий для преобразования, многопоточность на Java будет преобразована в Go код без испоьзования перевода в channels.
Converter выдал:
Всем большое спасибо. Любое Ваше мнение будет интересно.
Нижеприведенные примеры показывают, что удалось сделать на данный момент.
Работа это даже не прототип, а скорее указывает возможность достижения результата. Для чего я сознательно упрощаю контекст разработки Converter-a где это будет возможно.
Сначала мне показалось важным, что между Java и Go есть разница между реализацией Dynamic Dispatching, точнее в Go Dynamic Dispatching отсутствует.
Отсутствие Dynamic Dispatching в Go пока заставляет меня сделать (недостаток опыта в Go)текущее решение задачи несколько безобразно. Но вариант выгдядет вполне работающим. Скорее всего, авторы Go решают стандартные задачи OO другим путем.
Далее я буду приводить код на Java, за ним следует автоматически сгенерированный код на Golang и комментарии по-необходимости.
1. Начал я конечно с самой популярной программы: "Hello World".
Код: Выделить всё
package no.packeges;
public class HelloWorld {
public static void main( String[] args){
System.out.println("Hello World");
}
}
Код: Выделить всё
package main
import (
"fmt"
"os"
)
type HelloWorld struct{}
func main() {
var args []string = os.Args
var hw HelloWorld = HelloWorld{}
hw.HelloWorld_main(args)
}
/** generated method **/
func (helloWorld *HelloWorld) HelloWorld_main(args []string) {
fmt.Println("Hello World")
}
Код: Выделить всё
package no.packeges;
public class TestInheritance {
public static void main( String[] args){
Inheritance inh=null;
inh=new Second();
inh.hello();
inh=new Third();
inh.hello();
}
}
public interface Inheritance {
public void hello();
}
class Second implements Inheritance {
public void hello(){
System.out.println("Second");
}
}
class Third implements Inheritance {
public void hello(){
System.out.println("Third");
}
}
Код: Выделить всё
package main
import (
"fmt"
"os"
)
type TestInheritance struct{}
func main() {
var args []string = os.Args
var ti TestInheritance = TestInheritance{}
ti.TestInheritance_main(args)
}
/** generated method **/
func (testInheritance *TestInheritance) TestInheritance_main(args []string) {
var inh Inheritance
inh = AddressSecond(Second{})
inh.hello()
inh = AddressThird(Third{})
inh.hello()
}
type Inheritance interface {
hello()
}
type Second struct{}
func (second *Second) hello() {
fmt.Println("Second")
}
type Third struct{}
func (third *Third) hello() {
fmt.Println("Third")
}
func AddressSecond(s Second) *Second { return &s }
func AddressThird(t Third) *Third { return &t }
Код: Выделить всё
package no.packeges;
public class TestExtension {
public static void main( String[] args){
TestExtension te=new TestExtension();
te.hello();
te=new Second();
te.hello();
te=new Third();
te.hello();
te=new Fourth();
te.hello();
}
public void hello(){
System.out.println("hello");
}
}
class Second extends TestExtension {
public void hello(){
System.out.println("Second");
}
}
class Third extends TestExtension {
public void hello(){
System.out.println("Third");
}
}
class Fourth extends Third {
public void hello(){
System.out.println("Fourth");
}
}
Код: Выделить всё
package main
import (
"fmt"
"os"
)
type TestExtension struct{}
func main() {
var args []string = os.Args
var te TestExtension = TestExtension{}
te.TestExtension_main(args)
}
func (testExtension *TestExtension) hello() {
fmt.Println("hello")
}
/** generated method **/
func (testExtension *TestExtension) TestExtension_main(args []string) {
var te ITestExtension = AddressTestExtension(TestExtension{})
te.hello()
te = AddressSecond(Second{})
te.hello()
te = AddressThird(Third{})
te.hello()
te = AddressFourth(Fourth{})
te.hello()
}
type Second struct {
TestExtension
}
func (second *Second) hello() {
fmt.Println("Second")
}
type Third struct {
TestExtension
}
func (third *Third) hello() {
fmt.Println("Third")
}
type Fourth struct {
Third
}
func (fourth *Fourth) hello() {
fmt.Println("Fourth")
}
type ITestExtension interface { /** Generated Method */
hello()
}
func AddressSecond(s Second) *Second { return &s }
func AddressThird(t Third) *Third { return &t }
func AddressTestExtension(t TestExtension) *TestExtension
{ return &t }
func AddressFourth(f Fourth) *Fourth { return &f }
Проблемным методом в последнем примере является amount() в классе Repeater.
Без переписывания кода, я думаю, было бы невозможно вызвать его правильно.
Код: Выделить всё
package main;
public class Speaker {
String message;
public static void main( String[] args){
Speaker sp = new Speaker("Say hello !");
System.out.println(sp.amount());
sp.speak();
Repeater rp = new Repeater("Say hello !",3);
System.out.println(rp.amount());
rp.speak();
}
public Speaker( String message){
this.message=message;
}
public void speak(){
for (int i=0; i < amount(); i++) {
System.out.println(this.message);
}
}
public int amount(){
return 1;
}
}
class Repeater extends Speaker {
int to_repeat=0;
public Repeater( String message, int amount){
super(message);
this.to_repeat=amount;
}
public int amount(){
return this.to_repeat;
}
}
Код: Выделить всё
package main
import (
"fmt"
"os"
)
type Speaker struct {
message string
}
func main() {
var args []string = os.Args
var s_dummy Speaker = NewSpeaker("")
s_dummy.Speaker_main(args)
}
func NewSpeaker(message string) Speaker {
var speaker Speaker = Speaker{message}
return speaker
}
func (speaker *Speaker) speak() {
for i := 0; i < speaker.amount(); i++ {
fmt.Println(speaker.message)
}
}
func (speaker *Speaker) amount() int {
return 1
}
/** generated method **/
func (speaker *Speaker) Speaker_main(args []string) {
var sp ISpeaker = AddressSpeaker(NewSpeaker("Say hello !"))
fmt.Println(sp.amount())
sp.speak()
var rp ISpeaker = AddressRepeater(NewRepeater("Say hello !", 3))
fmt.Println(rp.amount())
rp.speak()
}
type Repeater struct {
Speaker
to_repeat int
}
func NewRepeater(message string, amount int) Repeater {
var repeater Repeater = Repeater{NewSpeaker(message), amount}
return repeater
}
func (repeater *Repeater) amount() int {
return repeater.to_repeat
}
func (repeater *Repeater) speak() {
for i := 0; i < repeater.amount(); i++ {
fmt.Println(repeater.message)
}
}
type ISpeaker interface {
/** Generated Method */
amount() int
/** Generated Method */
speak()
}
func AddressRepeater(r Repeater) *Repeater { return &r }
func AddressSpeaker(s Speaker) *Speaker { return &s }
Код: Выделить всё
package com.builder.start.here;
public class CatchException {
public static void main(String[] args) {
try {
new ThrowException().runme();
} catch (Exception e) {
System.out.println("yes, I caught it");
} finally {
System.out.println("finally processing");
}
}
}
class ThrowException{
public void runme() throws Exception{
throw new Exception();
}
}
Код: Выделить всё
package main
import (
"fmt"
"os"
)
type CatchException struct{}
func main() {
var args []string = os.Args
var ce CatchException = CatchException{}
ce.CatchException_main(args)
}
/** generated method **/
func (catchException *CatchException) CatchException_main(args []string) {
defer func() {
if err := recover(); err != nil {
exc := err.(Exception)
switch exc.msg {
case "Exception":
fmt.Println("yes, I caught it")
default:
fmt.Println("No, something is not right")
}
}
fmt.Println("finally processing")
}()
(&ThrowException{}).runme()
}
type ThrowException struct{}
func (throwException *ThrowException) runme() {
panic(Exception{"Exception"})
}
type Exception struct {
msg string
}
Нашел у Oracle простой пример с чудным названием BadThreads там:
https://docs.oracle.com/javase/tutor...questions.html, еще более упростил его, обозвал пример новым простым именем One и дополнил Converter, что бы перевести код на Golang.
В go нет похожей обработки для InterruptedException поэтому Converter не переводит обработку данного прерывания никак.
Код: Выделить всё
package run.me;
public class One {
String msg;
public static void main( String[] args)
throws InterruptedException {
One one=new One();
one.msg="Initial message";
System.out.println("main:before start:" +
one.msg + " second part of");
new Second(one).start();
one.msg="after go start";
Thread.sleep(2000);
System.out.println("main:about to end:" + one.msg);
}
}
class Second extends Thread {
One one;
public Second( One one){
this.one=one;
}
public void run(){
try {
sleep(1000);
} catch ( InterruptedException e) {
}
System.out.println("run:after sleep:" + one.msg);
one.msg="try to change msg";
}
}
Код: Выделить всё
package main
import (
"fmt"
"os"
"time"
)
type One struct {
msg *string
}
func NewOne() *One {
var one One = One{}
return &one
}
func main() {
var args []string = os.Args
var o_dummy *One = NewOne()
o_dummy.One_main(&args)
}
/** generated method **/
func (one_one *One) One_main(args *[]string) {
var one *One = NewOne()
s := "Initial message"
one.msg = &s
fmt.Println("main:before start:" +
*one.msg + " second part of")
go NewSecond(one).run()
s_s := "after go start"
one.msg = &s_s
time.Sleep(2000)
fmt.Println("main:about to end:" + *one.msg)
}
type Second struct {
one *One
}
func NewSecond(one *One) *Second {
var second Second = Second{one}
return &second
}
func (second *Second) run() {
time.Sleep(1000)
fmt.Println("run:after sleep:" + *second.one.msg)
s_s_s := "try to change msg"
second.one.msg = &s_s_s
}
Нашел у Oracle подходящий пример ProducerConsumerExample там:
ProducerConsumerExample, где класс Drop - кандидат на преобразование в Go с использованием channels.
Но, сейчас привожу промежуточный результат без channels.
Еще, прочитал мнение, что преобразование Java кода где используются аннотации в runtime-е -невозможен. Надо исследовать проблему и попытаться понять возможно ли ее как-то решить. Прежде чем переводить проект из статуса "возможность достижения" в статус "прототип" надо посмотреть, что можно сделать с указанными проблемами применительно к аннотациям.
Код на Java:
Код: Выделить всё
package com.builder.start.here;
import java.util.Random;
public class RunMeDrop {
public static void main(String[] args) {
Drop drop = new Drop();
(new Thread(new Producer(drop))).start();
(new Thread(new Consumer(drop))).start();
}
}
class Drop {
// Message sent from producer
// to consumer.
private String message;
// True if consumer should wait
// for producer to send message,
// false if producer should wait for
// consumer to retrieve message.
private boolean empty = true;
public synchronized String take() {
// Wait until message is
// available.
while (empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = true;
// Notify producer that
// status has changed.
notifyAll();
return message;
}
public synchronized void put(String message) {
// Wait until message has
// been retrieved.
while (!empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = false;
// Store message.
this.message = message;
// Notify consumer that status
// has changed.
notifyAll();
}
}
class Consumer implements Runnable {
private Drop drop;
public Consumer(Drop drop) {
this.drop = drop;
}
public void run() {
Random random = new Random();
for (
String message = drop.take();
! message.equals("DONE");
message = drop.take()) {
System.out.format(
"MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
}
}
class Producer implements Runnable {
private Drop drop;
public Producer(Drop drop) {
this.drop = drop;
}
public void run() {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
Random random = new Random();
for (int i = 0; i < importantInfo.length; i++) {
drop.put(importantInfo[i]);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
drop.put("DONE");
}
}
Код: Выделить всё
package main
import (
"fmt"
"math/rand"
"os"
"sync"
"time"
)
type RunMe struct{}
func NewRunMe() *RunMe {
var runMe RunMe = RunMe{}
return &runMe
}
func main() {
var args []string = os.Args
var rm *RunMe = NewRunMe()
rm.RunMe_main(&args)
}
/** generated method **/
func (runMe *RunMe) RunMe_main(args *[]string) {
wg := &sync.WaitGroup{}
var drop *Drop = NewDrop()
wg.Add(1)
go (&Thread{NewProducer(drop)}).run(wg)
wg.Add(1)
go (&Thread{NewConsumer(drop)}).run(wg)
wg.Wait()
}
type Drop struct {
/** generated field */
cond *sync.Cond
message *string
empty *bool
}
func NewDrop() *Drop {
var drop Drop = Drop{}
drop.cond = sync.NewCond(&sync.Mutex{})
empty := true
drop.empty = &empty
return &drop
}
func (drop *Drop) take() string {
drop.cond.L.Lock()
for *drop.empty {
drop.cond.Wait()
}
*drop.empty = true
drop.cond.L.Unlock()
drop.cond.Broadcast()
return *drop.message
}
func (drop *Drop) put(message *string) {
drop.cond.L.Lock()
for !*drop.empty {
drop.cond.Wait()
}
*drop.empty = false
drop.message = message
drop.cond.L.Unlock()
drop.cond.Broadcast()
}
type Consumer struct {
drop *Drop
}
func NewConsumer(drop *Drop) *Consumer {
var consumer Consumer = Consumer{drop}
return &consumer
}
func (consumer *Consumer) run(wg *sync.WaitGroup) {
defer wg.Done()
var random *Random = NewRandom()
for message := consumer.drop.take();
message != "DONE";
message = consumer.drop.take() {
fmt.Printf("MESSAGE RECEIVED: %s\n", message)
time.Sleep(random.nextInt(5000))
}
}
type Producer struct {
drop *Drop
}
func NewProducer(drop *Drop) *Producer {
var producer Producer = Producer{drop}
return &producer
}
func (producer *Producer) run(wg *sync.WaitGroup) {
defer wg.Done()
var importantInfo [4]string = [4]string{
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too",
}
var random *Random = NewRandom()
for i := 0; i < len(importantInfo); i++ {
producer.drop.put(&importantInfo[i])
time.Sleep(random.nextInt(5000))
}
s := "DONE"
producer.drop.put(&s)
}
type Random struct{}
func NewRandom() *Random {
var random Random = Random{}
return &random
}
func (r *Random) nextInt(n int) time.Duration {
return time.Duration(rand.Intn(n))
}
type Thread struct {
Runnable
}
func (t *Thread) run(wg *sync.WaitGroup) {
t.Runnable.run(wg)
}
type Runnable interface {
run(wg *sync.WaitGroup)
}
Теперь converter может преобразовывать Java классы в Go channels где это возможно. Предыдущий пример содержит класс Drop, котрый соответствует критериям преобразования, что и показывает нижеприведенный код примера на Go. Соответственно, если converter "не найдет" класс подходящий для преобразования, многопоточность на Java будет преобразована в Go код без испоьзования перевода в channels.
Код: Выделить всё
package com.builder.start.here;
import java.util.Random;
public class RunMe {
public static void main(String[] args) {
Drop drop = new Drop();
(new Thread(new Producer(drop))).start();
(new Thread(new Consumer(drop))).start();
}
}
class Drop {
// Message sent from producer
// to consumer.
private String message;
// True if consumer should wait
// for producer to send message,
// false if producer should wait for
// consumer to retrieve message.
private boolean empty = true;
public synchronized String take() {
// Wait until message is
// available.
while (empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = true;
// Notify producer that
// status has changed.
notifyAll();
return message;
}
public synchronized void put(String message) {
// Wait until message has
// been retrieved.
while (!empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = false;
// Store message.
this.message = message;
// Notify consumer that status
// has changed.
notifyAll();
}
}
class Consumer implements Runnable {
private Drop drop;
public Consumer(Drop drop) {
this.drop = drop;
}
public void run() {
Random random = new Random();
for (
String message = drop.take();
! message.equals("DONE");
message = drop.take()) {
System.out.format(
"MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
}
}
class Producer implements Runnable {
private Drop drop;
public Producer(Drop drop) {
this.drop = drop;
}
public void run() {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
Random random = new Random();
for (int i = 0; i < importantInfo.length; i++) {
drop.put(importantInfo[i]);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
drop.put("DONE");
}
}
Код: Выделить всё
package main
import (
"fmt"
"math/rand"
"os"
"sync"
"time"
)
type RunMe struct{}
func NewRunMe() *RunMe {
var runMe RunMe = RunMe{}
return &runMe
}
func main() {
var args []string = os.Args
var rm *RunMe = NewRunMe()
rm.RunMe_main(&args)
}
/** generated method **/
func (runMe *RunMe) RunMe_main(args *[]string) {
wg := &sync.WaitGroup{}
var drop chan string = make(chan string)
wg.Add(1)
go (&Thread{NewProducer(drop)}).run(wg)
wg.Add(1)
go (&Thread{NewConsumer(drop)}).run(wg)
wg.Wait()
}
type Consumer struct {
drop chan string
}
func NewConsumer(drop chan string) *Consumer {
var consumer Consumer = Consumer{drop}
return &consumer
}
func (consumer *Consumer) run(wg *sync.WaitGroup) {
defer wg.Done()
var random *Random = NewRandom()
for message := <-consumer.drop;
message != "DONE";
message = <-consumer.drop {
fmt.Printf("MESSAGE RECEIVED: %s\n", message)
time.Sleep(random.nextInt(5000))
}
}
type Producer struct {
drop chan string
}
func NewProducer(drop chan string) *Producer {
var producer Producer = Producer{drop}
return &producer
}
func (producer *Producer) run(wg *sync.WaitGroup) {
defer wg.Done()
var importantInfo [4]string = [4]string{
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"}
var random *Random = NewRandom()
for i := 0; i < len(importantInfo); i++ {
producer.drop <- (importantInfo[i])
time.Sleep(random.nextInt(5000))
}
producer.drop <- ("DONE")
}
type Random struct{}
func NewRandom() *Random {
var random Random = Random{}
return &random
}
func (r *Random) nextInt(n int) time.Duration { return time.Duration(rand.Intn(n)) }
type Thread struct {
Runnable
}
func (t *Thread) run(wg *sync.WaitGroup) {
t.Runnable.run(wg)
}
type Runnable interface {
run(wg *sync.WaitGroup)
}